[IMP] phantomjs testing
authorAntony Lesuisse <al@openerp.com>
Sun, 16 Feb 2014 21:22:22 +0000 (22:22 +0100)
committerAntony Lesuisse <al@openerp.com>
Sun, 16 Feb 2014 21:22:22 +0000 (22:22 +0100)
- 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
openerp/addons/base/tests/test_ui_load.js [new file with mode: 0644]
openerp/addons/base/tests/test_xmlrpc.py
openerp/http.py
openerp/modules/registry.py
openerp/tests/common.py
openerp/tests/phantomtest.js

index 63136b3..bd66319 100644 (file)
@@ -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 (file)
index 0000000..9d76250
--- /dev/null
@@ -0,0 +1,4 @@
+// Load helper
+phantom.injectJs(phantom.args[0]);
+pt = new PhantomTest();
+pt.run("/", "console.log('ok')", "console");
index ab1d382..854e345 100644 (file)
@@ -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
index fe5b113..74d833e 100644 (file)
@@ -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
index a277d4f..78b7e5c 100644 (file)
@@ -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.
 
index 94cf02f..ecfd4f8 100644 (file)
@@ -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)
index 6112df2..e1cbbf7 100644 (file)
@@ -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);