cubicweb/devtools/qunit.py
changeset 11745 f79dc500a4e7
parent 11744 a6dc650bc230
child 11746 7cf5a915e2e9
equal deleted inserted replaced
11744:a6dc650bc230 11745:f79dc500a4e7
    17 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
    17 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
    18 from __future__ import absolute_import
    18 from __future__ import absolute_import
    19 
    19 
    20 import os, os.path as osp
    20 import os, os.path as osp
    21 import errno
    21 import errno
       
    22 import shutil
    22 from tempfile import mkdtemp
    23 from tempfile import mkdtemp
    23 from subprocess import Popen, PIPE, STDOUT
    24 from subprocess import Popen, PIPE, STDOUT
    24 
    25 
    25 from six.moves.queue import Queue, Empty
    26 from six.moves.queue import Queue, Empty
    26 
    27 
    36 from cubicweb.devtools.testlib import TemporaryDirectory
    37 from cubicweb.devtools.testlib import TemporaryDirectory
    37 
    38 
    38 
    39 
    39 class FirefoxHelper(object):
    40 class FirefoxHelper(object):
    40 
    41 
    41     def __init__(self, url=None):
    42     def __init__(self, url):
       
    43         self._url = url
    42         self._process = None
    44         self._process = None
    43         self._profile_dir = mkdtemp(prefix='cwtest-ffxprof-')
    45         self._profile_dir = None
    44         self.firefox_cmd = ['firefox', '-no-remote']
    46         self.firefox_cmd = ['firefox', '-no-remote']
    45         if os.name == 'posix':
    47         if os.name == 'posix':
    46             self.firefox_cmd = [osp.join(osp.dirname(__file__), 'data', 'xvfb-run.sh'),
    48             self.firefox_cmd = [osp.join(osp.dirname(__file__), 'data', 'xvfb-run.sh'),
    47                                 '-a', '-s', '-noreset -screen 0 800x600x24'] + self.firefox_cmd
    49                                 '-a', '-s', '-noreset -screen 0 800x600x24'] + self.firefox_cmd
       
    50 
       
    51     def __enter__(self):
       
    52         self._profile_dir = mkdtemp(prefix='cwtest-ffxprof-')
       
    53         isavailable, reason = self.test()
       
    54         if not isavailable:
       
    55             raise RuntimeError(
       
    56                 'firefox not available or not working properly (%s)' % reason)
       
    57         self.start()
       
    58         return self
       
    59 
       
    60     def __exit__(self, *exc_info):
       
    61         self.stop()
       
    62         shutil.rmtree(self._profile_dir, ignore_errors=True)
    48 
    63 
    49     def test(self):
    64     def test(self):
    50         try:
    65         try:
    51             proc = Popen(['firefox', '--help'], stdout=PIPE, stderr=STDOUT)
    66             proc = Popen(['firefox', '--help'], stdout=PIPE, stderr=STDOUT)
    52             stdout, _ = proc.communicate()
    67             stdout, _ = proc.communicate()
    55             if exc.errno == errno.ENOENT:
    70             if exc.errno == errno.ENOENT:
    56                 msg = '[%s] %s' % (errno.errorcode[exc.errno], exc.strerror)
    71                 msg = '[%s] %s' % (errno.errorcode[exc.errno], exc.strerror)
    57                 return False, msg
    72                 return False, msg
    58             raise
    73             raise
    59 
    74 
    60     def start(self, url):
    75     def start(self):
    61         self.stop()
    76         self.stop()
    62         cmd = self.firefox_cmd + ['-silent', '--profile', self._profile_dir,
    77         cmd = self.firefox_cmd + ['-silent', '--profile', self._profile_dir,
    63                                   '-url', url]
    78                                   '-url', self._url]
    64         with open(os.devnull, 'w') as fnull:
    79         with open(os.devnull, 'w') as fnull:
    65             self._process = Popen(cmd, stdout=fnull, stderr=fnull)
    80             self._process = Popen(cmd, stdout=fnull, stderr=fnull)
    66 
    81 
    67     def stop(self):
    82     def stop(self):
    68         if self._process is not None:
    83         if self._process is not None:
   120         QUnitView.depends = depends
   135         QUnitView.depends = depends
   121 
   136 
   122         while not self.test_queue.empty():
   137         while not self.test_queue.empty():
   123             self.test_queue.get(False)
   138             self.test_queue.get(False)
   124 
   139 
   125         browser = FirefoxHelper()
   140         with FirefoxHelper(self.config['base-url'] + '?vid=qunit') as browser:
   126         isavailable, reason = browser.test()
   141             test_count = 0
   127         if not isavailable:
   142             error = False
   128             self.fail('firefox not available or not working properly (%s)' % reason)
   143 
   129         browser.start(self.config['base-url'] + "?vid=qunit")
   144             def runtime_error(*data):
   130         test_count = 0
   145                 raise RuntimeError(*data)
   131         error = False
   146 
   132 
   147             while not error:
   133         def runtime_error(*data):
   148                 try:
   134             raise RuntimeError(*data)
   149                     result, test_name, msg = self.test_queue.get(timeout=timeout)
   135 
   150                     test_name = '%s (%s)' % (test_name, test_file)
   136         while not error:
   151                     if result is None:
   137             try:
   152                         break
   138                 result, test_name, msg = self.test_queue.get(timeout=timeout)
   153                     test_count += 1
   139                 test_name = '%s (%s)' % (test_name, test_file)
   154                     if result:
   140                 if result is None:
   155                         yield test_name, lambda *args: 1, ()
   141                     break
   156                     else:
   142                 test_count += 1
   157                         yield test_name, self.fail, (msg, )
   143                 if result:
   158                 except Empty:
   144                     yield test_name, lambda *args: 1, ()
   159                     error = True
   145                 else:
   160                     msg = '%s inactivity timeout (%is). %i test results received'
   146                     yield test_name, self.fail, (msg, )
   161                     yield test_file, runtime_error, (msg % (test_file, timeout, test_count), )
   147             except Empty:
   162 
   148                 error = True
       
   149                 msg = '%s inactivity timeout (%is). %i test results received'
       
   150                 yield test_file, runtime_error, (msg % (test_file, timeout, test_count), )
       
   151         browser.stop()
       
   152         if test_count <= 0 and not error:
   163         if test_count <= 0 and not error:
   153             yield test_name, runtime_error, ('No test yielded by qunit for %s' % test_file, )
   164             yield test_name, runtime_error, ('No test yielded by qunit for %s' % test_file, )
       
   165 
   154 
   166 
   155 class QUnitResultController(Controller):
   167 class QUnitResultController(Controller):
   156 
   168 
   157     __regid__ = 'qunit_result'
   169     __regid__ = 'qunit_result'
   158 
   170