Show More
@@ -50,21 +50,27 b' class TestController(object):' | |||||
50 | process = None |
|
50 | process = None | |
51 | #: str, process stdout+stderr |
|
51 | #: str, process stdout+stderr | |
52 | stdout = None |
|
52 | stdout = None | |
53 | #: bool, whether to capture process stdout & stderr |
|
|||
54 | buffer_output = False |
|
|||
55 |
|
53 | |||
56 | def __init__(self): |
|
54 | def __init__(self): | |
57 | self.cmd = [] |
|
55 | self.cmd = [] | |
58 | self.env = {} |
|
56 | self.env = {} | |
59 | self.dirs = [] |
|
57 | self.dirs = [] | |
60 |
|
58 | |||
61 |
def |
|
59 | def setup(self): | |
|
60 | """Create temporary directories etc. | |||
|
61 | ||||
|
62 | This is only called when we know the test group will be run. Things | |||
|
63 | created here may be cleaned up by self.cleanup(). | |||
|
64 | """ | |||
|
65 | pass | |||
|
66 | ||||
|
67 | def launch(self, buffer_output=False): | |||
62 | # print('*** ENV:', self.env) # dbg |
|
68 | # print('*** ENV:', self.env) # dbg | |
63 | # print('*** CMD:', self.cmd) # dbg |
|
69 | # print('*** CMD:', self.cmd) # dbg | |
64 | env = os.environ.copy() |
|
70 | env = os.environ.copy() | |
65 | env.update(self.env) |
|
71 | env.update(self.env) | |
66 |
output = subprocess.PIPE if |
|
72 | output = subprocess.PIPE if buffer_output else None | |
67 |
stdout = subprocess.STDOUT if |
|
73 | stdout = subprocess.STDOUT if buffer_output else None | |
68 | self.process = subprocess.Popen(self.cmd, stdout=output, |
|
74 | self.process = subprocess.Popen(self.cmd, stdout=output, | |
69 | stderr=stdout, env=env) |
|
75 | stderr=stdout, env=env) | |
70 |
|
76 | |||
@@ -72,14 +78,17 b' class TestController(object):' | |||||
72 | self.stdout, _ = self.process.communicate() |
|
78 | self.stdout, _ = self.process.communicate() | |
73 | return self.process.returncode |
|
79 | return self.process.returncode | |
74 |
|
80 | |||
75 |
def |
|
81 | def print_extra_info(self): | |
76 | """Print buffered results of a test failure. |
|
82 | """Print extra information about this test run. | |
|
83 | ||||
|
84 | If we're running in parallel and showing the concise view, this is only | |||
|
85 | called if the test group fails. Otherwise, it's called before the test | |||
|
86 | group is started. | |||
77 |
|
87 | |||
78 | Called after tests fail while running in parallel. The base |
|
88 | The base implementation does nothing, but it can be overridden by | |
79 | implementation just prints the output from the test subprocess, but |
|
89 | subclasses. | |
80 | subclasses can override it to add extra information. |
|
|||
81 | """ |
|
90 | """ | |
82 | print(self.stdout) |
|
91 | return | |
83 |
|
92 | |||
84 | def cleanup_process(self): |
|
93 | def cleanup_process(self): | |
85 | """Cleanup on exit by killing any leftover processes.""" |
|
94 | """Cleanup on exit by killing any leftover processes.""" | |
@@ -125,6 +134,8 b' class PyTestController(TestController):' | |||||
125 | # pycmd is put into cmd[2] in PyTestController.launch() |
|
134 | # pycmd is put into cmd[2] in PyTestController.launch() | |
126 | self.cmd = [sys.executable, '-c', None, section] |
|
135 | self.cmd = [sys.executable, '-c', None, section] | |
127 | self.pycmd = "from IPython.testing.iptest import run_iptest; run_iptest()" |
|
136 | self.pycmd = "from IPython.testing.iptest import run_iptest; run_iptest()" | |
|
137 | ||||
|
138 | def setup(self): | |||
128 | ipydir = TemporaryDirectory() |
|
139 | ipydir = TemporaryDirectory() | |
129 | self.dirs.append(ipydir) |
|
140 | self.dirs.append(ipydir) | |
130 | self.env['IPYTHONDIR'] = ipydir.name |
|
141 | self.env['IPYTHONDIR'] = ipydir.name | |
@@ -164,9 +175,9 b' class PyTestController(TestController):' | |||||
164 | self.env['COVERAGE_PROCESS_START'] = config_file |
|
175 | self.env['COVERAGE_PROCESS_START'] = config_file | |
165 | self.pycmd = "import coverage; coverage.process_startup(); " + self.pycmd |
|
176 | self.pycmd = "import coverage; coverage.process_startup(); " + self.pycmd | |
166 |
|
177 | |||
167 | def launch(self): |
|
178 | def launch(self, buffer_output=False): | |
168 | self.cmd[2] = self.pycmd |
|
179 | self.cmd[2] = self.pycmd | |
169 | super(PyTestController, self).launch() |
|
180 | super(PyTestController, self).launch(buffer_output=buffer_output) | |
170 |
|
181 | |||
171 | js_prefix = 'js/' |
|
182 | js_prefix = 'js/' | |
172 |
|
183 | |||
@@ -187,14 +198,13 b' class JSController(TestController):' | |||||
187 | TestController.__init__(self) |
|
198 | TestController.__init__(self) | |
188 | self.section = section |
|
199 | self.section = section | |
189 |
|
200 | |||
190 |
|
201 | def setup(self): | ||
191 | def launch(self): |
|
|||
192 | self.ipydir = TemporaryDirectory() |
|
202 | self.ipydir = TemporaryDirectory() | |
193 | self.nbdir = TemporaryDirectory() |
|
203 | self.nbdir = TemporaryDirectory() | |
194 | os.makedirs(os.path.join(self.nbdir.name, os.path.join(u'sub βir1', u'sub βir 1a'))) |
|
|||
195 | os.makedirs(os.path.join(self.nbdir.name, os.path.join(u'sub βir2', u'sub βir 1b'))) |
|
|||
196 | self.dirs.append(self.ipydir) |
|
204 | self.dirs.append(self.ipydir) | |
197 | self.dirs.append(self.nbdir) |
|
205 | self.dirs.append(self.nbdir) | |
|
206 | os.makedirs(os.path.join(self.nbdir.name, os.path.join(u'sub βir1', u'sub βir 1a'))) | |||
|
207 | os.makedirs(os.path.join(self.nbdir.name, os.path.join(u'sub βir2', u'sub βir 1b'))) | |||
198 |
|
208 | |||
199 | # start the ipython notebook, so we get the port number |
|
209 | # start the ipython notebook, so we get the port number | |
200 | self._init_server() |
|
210 | self._init_server() | |
@@ -203,7 +213,9 b' class JSController(TestController):' | |||||
203 | test_cases = os.path.join(js_test_dir, self.section[len(js_prefix):]) |
|
213 | test_cases = os.path.join(js_test_dir, self.section[len(js_prefix):]) | |
204 | port = '--port=' + str(self.server_port) |
|
214 | port = '--port=' + str(self.server_port) | |
205 | self.cmd = ['casperjs', 'test', port, includes, test_cases] |
|
215 | self.cmd = ['casperjs', 'test', port, includes, test_cases] | |
206 | super(JSController, self).launch() |
|
216 | ||
|
217 | def print_extra_info(self): | |||
|
218 | print("Running tests with notebook directory %r" % self.nbdir.name) | |||
207 |
|
219 | |||
208 | @property |
|
220 | @property | |
209 | def will_run(self): |
|
221 | def will_run(self): | |
@@ -216,10 +228,6 b' class JSController(TestController):' | |||||
216 | self.server.start() |
|
228 | self.server.start() | |
217 | self.server_port = q.get() |
|
229 | self.server_port = q.get() | |
218 |
|
230 | |||
219 | def dump_failure(self): |
|
|||
220 | print("Ran tests with notebook directory %r" % self.nbdir.name) |
|
|||
221 | super(JSController, self).dump_failure() |
|
|||
222 |
|
||||
223 | def cleanup(self): |
|
231 | def cleanup(self): | |
224 | self.server.terminate() |
|
232 | self.server.terminate() | |
225 | self.server.join() |
|
233 | self.server.join() | |
@@ -287,10 +295,27 b' def configure_py_controllers(controllers, xunit=False, coverage=False,' | |||||
287 | controller.env['IPTEST_SUBPROC_STREAMS'] = subproc_streams |
|
295 | controller.env['IPTEST_SUBPROC_STREAMS'] = subproc_streams | |
288 | controller.cmd.extend(extra_args) |
|
296 | controller.cmd.extend(extra_args) | |
289 |
|
297 | |||
290 | def do_run(controller): |
|
298 | def do_run(controller, buffer_output=True): | |
|
299 | """Setup and run a test controller. | |||
|
300 | ||||
|
301 | If buffer_output is True, no output is displayed, to avoid it appearing | |||
|
302 | interleaved. In this case, the caller is responsible for displaying test | |||
|
303 | output on failure. | |||
|
304 | ||||
|
305 | Returns | |||
|
306 | ------- | |||
|
307 | controller : TestController | |||
|
308 | The same controller as passed in, as a convenience for using map() type | |||
|
309 | APIs. | |||
|
310 | exitcode : int | |||
|
311 | The exit code of the test subprocess. Non-zero indicates failure. | |||
|
312 | """ | |||
291 | try: |
|
313 | try: | |
292 | try: |
|
314 | try: | |
293 |
controller. |
|
315 | controller.setup() | |
|
316 | if not buffer_output: | |||
|
317 | controller.print_extra_info() | |||
|
318 | controller.launch(buffer_output=buffer_output) | |||
294 | except Exception: |
|
319 | except Exception: | |
295 | import traceback |
|
320 | import traceback | |
296 | traceback.print_exc() |
|
321 | traceback.print_exc() | |
@@ -377,10 +402,6 b' def run_iptestall(options):' | |||||
377 | extra_args : list |
|
402 | extra_args : list | |
378 | Extra arguments to pass to the test subprocesses, e.g. '-v' |
|
403 | Extra arguments to pass to the test subprocesses, e.g. '-v' | |
379 | """ |
|
404 | """ | |
380 | if options.fast != 1: |
|
|||
381 | # If running in parallel, capture output so it doesn't get interleaved |
|
|||
382 | TestController.buffer_output = True |
|
|||
383 |
|
||||
384 | to_run, not_run = prepare_controllers(options) |
|
405 | to_run, not_run = prepare_controllers(options) | |
385 |
|
406 | |||
386 | def justify(ltext, rtext, width=70, fill='-'): |
|
407 | def justify(ltext, rtext, width=70, fill='-'): | |
@@ -398,7 +419,7 b' def run_iptestall(options):' | |||||
398 | for controller in to_run: |
|
419 | for controller in to_run: | |
399 | print('IPython test group:', controller.section) |
|
420 | print('IPython test group:', controller.section) | |
400 | sys.stdout.flush() # Show in correct order when output is piped |
|
421 | sys.stdout.flush() # Show in correct order when output is piped | |
401 | controller, res = do_run(controller) |
|
422 | controller, res = do_run(controller, buffer_output=False) | |
402 | if res: |
|
423 | if res: | |
403 | failed.append(controller) |
|
424 | failed.append(controller) | |
404 | if res == -signal.SIGINT: |
|
425 | if res == -signal.SIGINT: | |
@@ -414,7 +435,8 b' def run_iptestall(options):' | |||||
414 | res_string = 'OK' if res == 0 else 'FAILED' |
|
435 | res_string = 'OK' if res == 0 else 'FAILED' | |
415 | print(justify('Test group: ' + controller.section, res_string)) |
|
436 | print(justify('Test group: ' + controller.section, res_string)) | |
416 | if res: |
|
437 | if res: | |
417 |
controller. |
|
438 | controller.print_extra_info() | |
|
439 | print(bytes_to_str(controller.stdout)) | |||
418 | failed.append(controller) |
|
440 | failed.append(controller) | |
419 | if res == -signal.SIGINT: |
|
441 | if res == -signal.SIGINT: | |
420 | print("Interrupted") |
|
442 | print("Interrupted") |
General Comments 0
You need to be logged in to leave comments.
Login now