7 ROOT = os.path.join(os.path.dirname(__file__), 'grunt')
9 __all__ = ['QUnitSuite']
11 def _exc_info_to_string(err, test):
14 class QUnitTest(unittest.TestCase):
15 def __init__(self, module, name):
19 def shortDescription(self):
22 return '<QUnitTest %s:%s>' % (self.module, self.name)
24 return '%s: %s' % (self.module, self.name)
26 class QUnitSuite(unittest.TestSuite):
27 def __init__(self, qunitfile, timeout=5000):
28 super(QUnitSuite, self).__init__()
29 self.testfile = qunitfile
30 self.timeout = timeout
34 def run(self, result):
36 subprocess.call(['phantomjs', '-v'],
37 stdout=open(os.devnull, 'w'),
38 stderr=subprocess.STDOUT)
40 test = QUnitTest('phantomjs', 'javascript tests')
41 result.startTest(test)
42 result.startTest(test)
43 result.addSkip(test , "phantomjs command not found")
47 result._exc_info_to_string = _exc_info_to_string
51 del result._exc_info_to_string
53 def _run(self, result):
54 phantom = subprocess.Popen([
56 '--config=%s' % os.path.join(ROOT, 'phantomjs.json'),
57 os.path.join(ROOT, 'bootstrap.js'), self.testfile,
59 'timeout': self.timeout,
60 'inject': os.path.join(ROOT, 'qunit-phantomjs-bridge.js')
62 ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
66 line = phantom.stdout.readline()
68 if self.process(line, result):
73 # If the phantomjs process hasn't quit, kill it
74 if phantom.poll() is None:
77 def process(self, line, result):
79 args = json.loads(line)
80 except ValueError: # phantomjs stderr
81 if 'CoreText' not in line:
86 if event_name == 'qunit.done':
88 elif event_name == 'fail.load':
89 self.add_error(result, "PhantomJS unable to load %s" % args[1])
91 elif event_name == 'fail.timeout':
92 self.add_error(result, "PhantomJS timed out, possibly due to a"
93 " missing QUnit start() call")
96 elif event_name == 'qunit.moduleStart':
97 self._module = args[1].encode('utf-8') if args[1] else ''
98 elif event_name == 'qunit.moduleStop':
101 elif event_name == 'qunit.testStart':
102 self._test = QUnitTest(self._module, args[1].encode('utf-8'))
103 result.startTest(self._test)
104 elif event_name == 'qunit.testDone':
105 if not self._test.failed:
106 result.addSuccess(self._test)
107 result.stopTest(self._test)
109 elif event_name == 'qunit.log':
113 self._test.failed = True
115 self._test, self.failure_to_str(*args[2:]))
116 elif event_name == 'console':
121 def add_error(self, result, s):
122 test = QUnitTest('phantomjs', 'startup')
123 result.startTest(test)
124 result.addError(test, s)
125 result.stopTest(test)
127 def failure_to_str(self, actual, expected, message, source):
128 if message or actual == expected:
129 formatted = str(message or '')
131 formatted = "%s != %s" % (actual, expected)
134 formatted += '\n\n' + source