From c8324bafccf0ab4ca808c97918db3dbb04a8890f Mon Sep 17 00:00:00 2001 From: Antony Lesuisse Date: Sun, 16 Feb 2014 22:22:22 +0100 Subject: [PATCH] [IMP] phantomjs testing - avoid dbmanager by presetting db in the test session - correctly handle login option - serialize test cursor access bzr revid: al@openerp.com-20140216212222-4o6x9uljyua3g1og --- openerp/addons/base/tests/test_ui.py | 12 ++++--- openerp/addons/base/tests/test_ui_load.js | 4 +++ openerp/addons/base/tests/test_xmlrpc.py | 17 ++++----- openerp/http.py | 19 +++++----- openerp/modules/registry.py | 9 ----- openerp/tests/common.py | 44 +++++++++++++++++------ openerp/tests/phantomtest.js | 18 ++++------ 7 files changed, 71 insertions(+), 52 deletions(-) create mode 100644 openerp/addons/base/tests/test_ui_load.js diff --git a/openerp/addons/base/tests/test_ui.py b/openerp/addons/base/tests/test_ui.py index 63136b36a31..bd663197253 100644 --- a/openerp/addons/base/tests/test_ui.py +++ b/openerp/addons/base/tests/test_ui.py @@ -4,10 +4,14 @@ import os import openerp class TestUi(openerp.tests.HttpCase): - def test_js(self): - self.phantom_js('/',"console.log('ok')","console", login=None) - - def test_jsfile(self): + def test_01_jsfile_ui_hello(self): self.phantom_jsfile(os.path.join(os.path.dirname(__file__), 'test_ui_hello.js')) + def test_02_jsfile_ui_load(self): + self.phantom_jsfile(os.path.join(os.path.dirname(__file__), 'test_ui_load.js')) + def test_03_js_public(self): + self.phantom_js('/',"console.log('ok')","console") + def test_04_js_admin(self): + self.phantom_js('/',"console.log('ok')","openerp.client.action_manager.inner_widget.views.kanban", login='admin') + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/addons/base/tests/test_ui_load.js b/openerp/addons/base/tests/test_ui_load.js new file mode 100644 index 00000000000..9d76250d239 --- /dev/null +++ b/openerp/addons/base/tests/test_ui_load.js @@ -0,0 +1,4 @@ +// Load helper +phantom.injectJs(phantom.args[0]); +pt = new PhantomTest(); +pt.run("/", "console.log('ok')", "console"); diff --git a/openerp/addons/base/tests/test_xmlrpc.py b/openerp/addons/base/tests/test_xmlrpc.py index ab1d3821c40..854e345078a 100644 --- a/openerp/addons/base/tests/test_xmlrpc.py +++ b/openerp/addons/base/tests/test_xmlrpc.py @@ -3,26 +3,23 @@ import time import unittest2 import xmlrpclib -from openerp.tests import common +import openerp -DB = common.DB -ADMIN_USER = common.ADMIN_USER -ADMIN_USER_ID = common.ADMIN_USER_ID -ADMIN_PASSWORD = common.ADMIN_PASSWORD +DB = openerp.tests.common.DB -class test_xmlrpc(common.HttpCase): +class test_xmlrpc(openerp.tests.common.HttpCase): def test_01_xmlrpc_login(self): """ Try to login on the common service. """ - uid = self.xmlrpc_common.login(DB, ADMIN_USER, ADMIN_PASSWORD) - self.assertTrue(uid == ADMIN_USER_ID) + uid = self.xmlrpc_common.login(DB, 'admin', 'admin') + self.assertTrue(uid == 1) def test_xmlrpc_ir_model_search(self): """ Try a search on the object service. """ o = self.xmlrpc_object - ids = o.execute(DB, ADMIN_USER_ID, ADMIN_PASSWORD, 'ir.model', 'search', []) + ids = o.execute(DB, 1, 'admin', 'ir.model', 'search', []) self.assertIsInstance(ids, list) - ids = o.execute(DB, ADMIN_USER_ID, ADMIN_PASSWORD, 'ir.model', 'search', [], {}) + ids = o.execute(DB, 1, 'admin', 'ir.model', 'search', [], {}) self.assertIsInstance(ids, list) # This test was written to test the creation of a new RPC endpoint, not diff --git a/openerp/http.py b/openerp/http.py index fe5b113d286..74d833e4730 100644 --- a/openerp/http.py +++ b/openerp/http.py @@ -168,9 +168,9 @@ class WebRequest(object): """ # some magic to lazy create the cr if not self._cr: - if openerp.tools.config['test_enable'] and self.session_id in openerp.tests.common.HTTP_SESSION: - self._cr = openerp.tests.common.HTTP_SESSION[self.session_id] - else: + # Test cursors + self._cr = openerp.tests.common.acquire_test_cursor(self.session_id) + if not self._cr: self._cr = self.registry.db.cursor() return self._cr @@ -180,10 +180,13 @@ class WebRequest(object): def __exit__(self, exc_type, exc_value, traceback): _request_stack.pop() - if self._cr and not (openerp.tools.config['test_enable'] and self.session_id in openerp.tests.common.HTTP_SESSION): - if exc_type is None: - self._cr.commit() - self._cr.close() + + if self._cr: + # Dont commit test cursors + if not openerp.tests.common.release_test_cursor(self.session_id): + if exc_type is None: + self._cr.commit() + self._cr.close() # just to be sure no one tries to re-use the request self.disable_db = True self.uid = None @@ -595,7 +598,7 @@ class Service(object): class Model(object): """ .. deprecated:: 8.0 - Use the resistry and cursor in ``openerp.addons.web.http.request`` instead. + Use the resistry and cursor in ``openerp.http.request`` instead. """ def __init__(self, session, model): self.session = session diff --git a/openerp/modules/registry.py b/openerp/modules/registry.py index a277d4f6402..78b7e5caeab 100644 --- a/openerp/modules/registry.py +++ b/openerp/modules/registry.py @@ -209,15 +209,6 @@ class TestRLock(object): def __exit__(self, type, value, traceback): self.release() -# def __enter__(self, *l, **kw): -# if openerp.tools.config['test_enable']: -# return -# return super(TestRlock, self).__enter__(*l, **kw) -# def __exit__(self, *l, **kw): -# if openerp.tools.config['test_enable']: -# return -# return super(TestRlock, self).__exit__(*l, **kw) - class RegistryManager(object): """ Model registries manager. diff --git a/openerp/tests/common.py b/openerp/tests/common.py index 94cf02f42d8..ecfd4f84894 100644 --- a/openerp/tests/common.py +++ b/openerp/tests/common.py @@ -15,6 +15,7 @@ import time import unittest2 import uuid import xmlrpclib +import threading import openerp @@ -25,20 +26,36 @@ ADDONS_PATH = openerp.tools.config['addons_path'] HOST = '127.0.0.1' PORT = openerp.tools.config['xmlrpc_port'] DB = openerp.tools.config['db_name'] - # If the database name is not provided on the command-line, # use the one on the thread (which means if it is provided on # the command-line, this will break when installing another # database from XML-RPC). if not DB and hasattr(threading.current_thread(), 'dbname'): DB = threading.current_thread().dbname - -ADMIN_USER = 'admin' +# Useless constant, tests are aware of the content of demo data ADMIN_USER_ID = openerp.SUPERUSER_ID -ADMIN_PASSWORD = 'admin' +# Magic session_id, unfortunately we have to serialize access to the cursors to +# serialize requests. We first tried to duplicate the database for each tests +# but this proved too slow. Any idea to improve this is welcome. HTTP_SESSION = {} +def acquire_test_cursor(session_id): + if openerp.tools.config['test_enable']: + cr = HTTP_SESSION.get(session_id) + if cr: + cr._test_lock.acquire() + return cr + +def release_test_cursor(session_id): + if openerp.tools.config['test_enable']: + cr = HTTP_SESSION.get(session_id) + if cr: + cr._test_lock.release() + return True + return False + + class BaseCase(unittest2.TestCase): """ Subclass of TestCase for common OpenERP-specific code. @@ -126,9 +143,15 @@ class HttpCase(TransactionCase): def setUp(self): super(HttpCase, self).setUp() - self.session_id = uuid.uuid4().hex + # setup a magic session_id that will be rollbacked + self.session = openerp.http.root.session_store.new() + self.session_id = self.session.sid + self.session.db = DB + openerp.http.root.session_store.save(self.session) + self.cr._test_lock = threading.RLock() HTTP_SESSION[self.session_id] = self.cr + def tearDown(self): del HTTP_SESSION[self.session_id] super(HttpCase, self).tearDown() @@ -198,8 +221,9 @@ class HttpCase(TransactionCase): cmd = ['phantomjs', jsfile, phantomtest, json.dumps(options)] self.phantom_run(cmd, timeout) - def phantom_js(self, url_path, code, ready="window", timeout=30, **kw): + def phantom_js(self, url_path, code, ready="window", login=None, timeout=30, **kw): """ Test js code running in the browser + - optionnally log as 'login' - load page given by url_path - wait for ready object to be available - eval(code) inside the page @@ -213,17 +237,17 @@ class HttpCase(TransactionCase): If neither are done before timeout test fails. """ options = { + 'port': PORT, + 'db': DB, 'url_path': url_path, 'code': code, 'ready': ready, 'timeout' : timeout, - 'port': PORT, - 'db': DB, - 'login': ADMIN_USER, - 'password': ADMIN_PASSWORD, + 'login' : login, 'session_id': self.session_id, } options.update(kw) + options.setdefault('password', options.get('login')) phantomtest = os.path.join(os.path.dirname(__file__), 'phantomtest.js') cmd = ['phantomjs', phantomtest, json.dumps(options)] self.phantom_run(cmd, timeout) diff --git a/openerp/tests/phantomtest.js b/openerp/tests/phantomtest.js index 6112df24107..e1cbbf735de 100644 --- a/openerp/tests/phantomtest.js +++ b/openerp/tests/phantomtest.js @@ -24,11 +24,7 @@ function waitFor (ready, callback, timeout, timeoutMessageCallback) { function PhantomTest() { var self = this; - if(phantom.args.length === 1) { - this.options = JSON.parse(phantom.args[0]); - } else { - this.options = JSON.parse(phantom.args[1]); - } + this.options = JSON.parse(phantom.args[phantom.args.length-1]); this.inject = []; this.timeout = this.options.timeout ? Math.round(parseFloat(this.options.timeout)*1000 - 5000) : 10000; this.origin = 'http://localhost'; @@ -44,15 +40,15 @@ function PhantomTest() { }; // ---------------------------------------------------- - // configure page + // configure phantom and page // ---------------------------------------------------- - this.page = require('webpage').create(); - this.page.viewportSize = { width: 1366, height: 768 }; - this.page.addCookie({ + phantom.addCookie({ 'domain': 'localhost', 'name': 'session_id', 'value': this.options.session_id, }); + this.page = require('webpage').create(); + this.page.viewportSize = { width: 1366, height: 768 }; this.page.onError = function(message, trace) { self.error(message + " " + trace); }; @@ -101,7 +97,7 @@ function PhantomTest() { qp.push('login=' + self.options.login); qp.push('key=' + self.options.password); qp.push('redirect=' + encodeURIComponent(url_path)); - var url_path = "/web/login?" + qp.join('&'); + var url_path = "/login?" + qp.join('&'); } var url = self.origin + url_path; self.page.open(url, function(status) { @@ -116,7 +112,7 @@ function PhantomTest() { try { r = !!eval(ready); } catch(ex) { - console.log("waiting for page " + ready) + console.log("waiting for " + ready) }; return r; }, ready);