Show More
@@ -1,7 +1,6 | |||||
1 | // |
|
1 | // | |
2 | // Utility functions for the HTML notebook's CasperJS tests. |
|
2 | // Utility functions for the HTML notebook's CasperJS tests. | |
3 | // |
|
3 | // | |
4 |
|
||||
5 | casper.get_notebook_server = function () { |
|
4 | casper.get_notebook_server = function () { | |
6 | // Get the URL of a notebook server on which to run tests. |
|
5 | // Get the URL of a notebook server on which to run tests. | |
7 | port = casper.cli.get("port"); |
|
6 | port = casper.cli.get("port"); | |
@@ -32,6 +31,15 casper.open_new_notebook = function () { | |||||
32 | IPython._status = 'busy'; |
|
31 | IPython._status = 'busy'; | |
33 | }); |
|
32 | }); | |
34 | }); |
|
33 | }); | |
|
34 | ||||
|
35 | // Because of the asynchronous nature of SlimerJS (Gecko), we need to make | |||
|
36 | // sure the notebook has actually been loaded into the IPython namespace | |||
|
37 | // before running any tests. | |||
|
38 | this.waitFor(function() { | |||
|
39 | return this.evaluate(function () { | |||
|
40 | return IPython.notebook; | |||
|
41 | }); | |||
|
42 | }); | |||
35 | }; |
|
43 | }; | |
36 |
|
44 | |||
37 | casper.kernel_running = function kernel_running() { |
|
45 | casper.kernel_running = function kernel_running() { | |
@@ -411,9 +419,30 casper.cell_has_class = function(index, classes) { | |||||
411 |
|
419 | |||
412 | casper.notebook_test = function(test) { |
|
420 | casper.notebook_test = function(test) { | |
413 | // Wrap a notebook test to reduce boilerplate. |
|
421 | // Wrap a notebook test to reduce boilerplate. | |
|
422 | // | |||
|
423 | // If you want to read parameters from the commandline, use the following | |||
|
424 | // (i.e. value=): | |||
|
425 | // if (casper.cli.options.value) { | |||
|
426 | // casper.exit(1); | |||
|
427 | // } | |||
414 | this.open_new_notebook(); |
|
428 | this.open_new_notebook(); | |
415 | this.then(test); |
|
|||
416 |
|
429 | |||
|
430 | // Echo whether or not we are running this test using SlimerJS | |||
|
431 | if (this.evaluate(function(){ | |||
|
432 | return typeof InstallTrigger !== 'undefined'; // Firefox 1.0+ | |||
|
433 | })) { console.log('This test is running in SlimerJS.'); } | |||
|
434 | ||||
|
435 | // Make sure to remove the onbeforeunload callback. This callback is | |||
|
436 | // responsable for the "Are you sure you want to quit?" type messages. | |||
|
437 | // PhantomJS ignores these prompts, SlimerJS does not which causes hangs. | |||
|
438 | this.then(function(){ | |||
|
439 | this.evaluate(function(){ | |||
|
440 | window.onbeforeunload = function(){}; | |||
|
441 | }); | |||
|
442 | }); | |||
|
443 | ||||
|
444 | this.then(test); | |||
|
445 | ||||
417 | // Kill the kernel and delete the notebook. |
|
446 | // Kill the kernel and delete the notebook. | |
418 | this.shutdown_current_kernel(); |
|
447 | this.shutdown_current_kernel(); | |
419 | // This is still broken but shouldn't be a problem for now. |
|
448 | // This is still broken but shouldn't be a problem for now. |
@@ -1,9 +1,15 | |||||
1 | var xor = function (a, b) {return !a ^ !b;}; |
|
1 | var xor = function (a, b) {return !a ^ !b;}; | |
2 | var isArray = function (a) {return toString.call(a) === "[object Array]" || toString.call(a) === "[object RuntimeArray]";}; |
|
2 | var isArray = function (a) { | |
|
3 | try { | |||
|
4 | return Object.toString.call(a) === "[object Array]" || Object.toString.call(a) === "[object RuntimeArray]"; | |||
|
5 | } catch (e) { | |||
|
6 | return Array.isArray(a); | |||
|
7 | } | |||
|
8 | }; | |||
3 | var recursive_compare = function(a, b) { |
|
9 | var recursive_compare = function(a, b) { | |
4 | // Recursively compare two objects. |
|
10 | // Recursively compare two objects. | |
5 | var same = true; |
|
11 | var same = true; | |
6 | same = same && !xor(a instanceof Object, b instanceof Object); |
|
12 | same = same && !xor(a instanceof Object || typeof a == 'object', b instanceof Object || typeof b == 'object'); | |
7 | same = same && !xor(isArray(a), isArray(b)); |
|
13 | same = same && !xor(isArray(a), isArray(b)); | |
8 |
|
14 | |||
9 | if (same) { |
|
15 | if (same) { |
@@ -148,6 +148,8 have['jinja2'] = test_for('jinja2') | |||||
148 | have['requests'] = test_for('requests') |
|
148 | have['requests'] = test_for('requests') | |
149 | have['sphinx'] = test_for('sphinx') |
|
149 | have['sphinx'] = test_for('sphinx') | |
150 | have['casperjs'] = is_cmd_found('casperjs') |
|
150 | have['casperjs'] = is_cmd_found('casperjs') | |
|
151 | have['phantomjs'] = is_cmd_found('phantomjs') | |||
|
152 | have['slimerjs'] = is_cmd_found('slimerjs') | |||
151 |
|
153 | |||
152 | min_zmq = (2,1,11) |
|
154 | min_zmq = (2,1,11) | |
153 |
|
155 |
@@ -20,12 +20,14 import signal | |||||
20 | import sys |
|
20 | import sys | |
21 | import subprocess |
|
21 | import subprocess | |
22 | import time |
|
22 | import time | |
|
23 | import re | |||
23 |
|
24 | |||
24 | from .iptest import have, test_group_names as py_test_group_names, test_sections, StreamCapturer |
|
25 | from .iptest import have, test_group_names as py_test_group_names, test_sections, StreamCapturer | |
25 | from IPython.utils.path import compress_user |
|
26 | from IPython.utils.path import compress_user | |
26 | from IPython.utils.py3compat import bytes_to_str |
|
27 | from IPython.utils.py3compat import bytes_to_str | |
27 | from IPython.utils.sysinfo import get_sys_info |
|
28 | from IPython.utils.sysinfo import get_sys_info | |
28 | from IPython.utils.tempdir import TemporaryDirectory |
|
29 | from IPython.utils.tempdir import TemporaryDirectory | |
|
30 | from IPython.nbconvert.filters.ansi import strip_ansi | |||
29 |
|
31 | |||
30 | try: |
|
32 | try: | |
31 | # Python >= 3.3 |
|
33 | # Python >= 3.3 | |
@@ -214,15 +216,17 def all_js_groups(): | |||||
214 | class JSController(TestController): |
|
216 | class JSController(TestController): | |
215 | """Run CasperJS tests """ |
|
217 | """Run CasperJS tests """ | |
216 | requirements = ['zmq', 'tornado', 'jinja2', 'casperjs', 'sqlite3'] |
|
218 | requirements = ['zmq', 'tornado', 'jinja2', 'casperjs', 'sqlite3'] | |
217 | def __init__(self, section, enabled=True): |
|
219 | def __init__(self, section, enabled=True, engine='phantomjs'): | |
218 | """Create new test runner.""" |
|
220 | """Create new test runner.""" | |
219 | TestController.__init__(self) |
|
221 | TestController.__init__(self) | |
|
222 | self.engine = engine | |||
220 | self.section = section |
|
223 | self.section = section | |
221 | self.enabled = enabled |
|
224 | self.enabled = enabled | |
|
225 | self.slimer_failure = re.compile('^FAIL.*', flags=re.MULTILINE) | |||
222 | js_test_dir = get_js_test_dir() |
|
226 | js_test_dir = get_js_test_dir() | |
223 | includes = '--includes=' + os.path.join(js_test_dir,'util.js') |
|
227 | includes = '--includes=' + os.path.join(js_test_dir,'util.js') | |
224 | test_cases = os.path.join(js_test_dir, self.section[len(js_prefix):]) |
|
228 | test_cases = os.path.join(js_test_dir, self.section[len(js_prefix):]) | |
225 | self.cmd = ['casperjs', 'test', includes, test_cases] |
|
229 | self.cmd = ['casperjs', 'test', includes, test_cases, '--engine=%s' % self.engine] | |
226 |
|
230 | |||
227 | def setup(self): |
|
231 | def setup(self): | |
228 | self.ipydir = TemporaryDirectory() |
|
232 | self.ipydir = TemporaryDirectory() | |
@@ -240,13 +244,31 class JSController(TestController): | |||||
240 | else: |
|
244 | else: | |
241 | # don't launch tests if the server didn't start |
|
245 | # don't launch tests if the server didn't start | |
242 | self.cmd = [sys.executable, '-c', 'raise SystemExit(1)'] |
|
246 | self.cmd = [sys.executable, '-c', 'raise SystemExit(1)'] | |
|
247 | ||||
|
248 | def launch(self, buffer_output): | |||
|
249 | # If the engine is SlimerJS, we need to buffer the output because | |||
|
250 | # SlimerJS does not support exit codes, therefor CasperJS always returns | |||
|
251 | # 0 which is a false positive. | |||
|
252 | buffer_output = (self.engine == 'slimerjs') or buffer_output | |||
|
253 | super(JSController, self).launch(buffer_output=buffer_output) | |||
|
254 | ||||
|
255 | def wait(self, *pargs, **kwargs): | |||
|
256 | """Wait for the JSController to finish""" | |||
|
257 | ret = super(JSController, self).wait(*pargs, **kwargs) | |||
|
258 | # If this is a SlimerJS controller, echo the captured output. | |||
|
259 | if self.engine == 'slimerjs': | |||
|
260 | print(self.stdout) | |||
|
261 | # Return True if a failure occured. | |||
|
262 | return self.slimer_failure.search(strip_ansi(self.stdout)) | |||
|
263 | else: | |||
|
264 | return ret | |||
243 |
|
265 | |||
244 | def print_extra_info(self): |
|
266 | def print_extra_info(self): | |
245 | print("Running tests with notebook directory %r" % self.nbdir.name) |
|
267 | print("Running tests with notebook directory %r" % self.nbdir.name) | |
246 |
|
268 | |||
247 | @property |
|
269 | @property | |
248 | def will_run(self): |
|
270 | def will_run(self): | |
249 | return self.enabled and all(have[a] for a in self.requirements) |
|
271 | return self.enabled and all(have[a] for a in self.requirements + [self.engine]) | |
250 |
|
272 | |||
251 | def _init_server(self): |
|
273 | def _init_server(self): | |
252 | "Start the notebook server in a separate process" |
|
274 | "Start the notebook server in a separate process" | |
@@ -281,7 +303,7 class JSController(TestController): | |||||
281 | # get invalid JSON; it should be ready next iteration. |
|
303 | # get invalid JSON; it should be ready next iteration. | |
282 | pass |
|
304 | pass | |
283 | else: |
|
305 | else: | |
284 |
|
|
306 | return | |
285 | time.sleep(0.1) |
|
307 | time.sleep(0.1) | |
286 | print("Notebook server-info file never arrived: %s" % self.server_info_file, |
|
308 | print("Notebook server-info file never arrived: %s" % self.server_info_file, | |
287 | file=sys.stderr |
|
309 | file=sys.stderr | |
@@ -350,7 +372,8 def prepare_controllers(options): | |||||
350 | else: |
|
372 | else: | |
351 | js_testgroups = all_js_groups() |
|
373 | js_testgroups = all_js_groups() | |
352 |
|
374 | |||
353 | c_js = [JSController(name) for name in js_testgroups] |
|
375 | engine = 'phantomjs' if have['phantomjs'] and not options.slimerjs else 'slimerjs' | |
|
376 | c_js = [JSController(name, engine=engine) for name in js_testgroups] | |||
354 | c_py = [PyTestController(name, options) for name in py_testgroups] |
|
377 | c_py = [PyTestController(name, options) for name in py_testgroups] | |
355 |
|
378 | |||
356 | controllers = c_py + c_js |
|
379 | controllers = c_py + c_js | |
@@ -455,6 +478,9 def run_iptestall(options): | |||||
455 | Include slow tests, like IPython.parallel. By default, these tests aren't |
|
478 | Include slow tests, like IPython.parallel. By default, these tests aren't | |
456 | run. |
|
479 | run. | |
457 |
|
480 | |||
|
481 | slimerjs : bool | |||
|
482 | Use slimerjs if it's installed instead of phantomjs for casperjs tests. | |||
|
483 | ||||
458 | xunit : bool |
|
484 | xunit : bool | |
459 | Produce Xunit XML output. This is written to multiple foo.xunit.xml files. |
|
485 | Produce Xunit XML output. This is written to multiple foo.xunit.xml files. | |
460 |
|
486 | |||
@@ -581,6 +607,8 argparser.add_argument('testgroups', nargs='*', | |||||
581 | 'all tests.') |
|
607 | 'all tests.') | |
582 | argparser.add_argument('--all', action='store_true', |
|
608 | argparser.add_argument('--all', action='store_true', | |
583 | help='Include slow tests not run by default.') |
|
609 | help='Include slow tests not run by default.') | |
|
610 | argparser.add_argument('--slimerjs', action='store_true', | |||
|
611 | help="Use slimerjs if it's installed instead of phantomjs for casperjs tests.") | |||
584 | argparser.add_argument('-j', '--fast', nargs='?', const=None, default=1, type=int, |
|
612 | argparser.add_argument('-j', '--fast', nargs='?', const=None, default=1, type=int, | |
585 | help='Run test sections in parallel. This starts as many ' |
|
613 | help='Run test sections in parallel. This starts as many ' | |
586 | 'processes as you have cores, or you can specify a number.') |
|
614 | 'processes as you have cores, or you can specify a number.') |
General Comments 0
You need to be logged in to leave comments.
Login now