##// END OF EJS Templates
Unify entry points for iptest
Thomas Kluyver -
Show More
@@ -130,20 +130,27 b' class PyTestController(TestController):'
130 130
131 131 @property
132 132 def will_run(self):
133 return test_sections[self.section].will_run
133 try:
134 return test_sections[self.section].will_run
135 except KeyError:
136 return True
134 137
135 138 def add_xunit(self):
136 139 xunit_file = os.path.abspath(self.section + '.xunit.xml')
137 140 self.cmd.extend(['--with-xunit', '--xunit-file', xunit_file])
138 141
139 142 def add_coverage(self):
143 try:
144 sources = test_sections[self.section].includes
145 except KeyError:
146 sources = ['IPython']
147
140 148 coverage_rc = ("[run]\n"
141 149 "data_file = {data_file}\n"
142 150 "source =\n"
143 151 " {source}\n"
144 152 ).format(data_file=os.path.abspath('.coverage.'+self.section),
145 source="\n ".join(test_sections[self.section].includes))
146
153 source="\n ".join(sources))
147 154 config_file = os.path.join(self.workingdir.name, '.coveragerc')
148 155 with open(config_file, 'w') as f:
149 156 f.write(coverage_rc)
@@ -156,7 +163,7 b' class PyTestController(TestController):'
156 163 super(PyTestController, self).launch()
157 164
158 165
159 def prepare_py_test_controllers(inc_slow=False, xunit=False, coverage=False):
166 def prepare_py_test_controllers(inc_slow=False):
160 167 """Returns an ordered list of PyTestController instances to be run."""
161 168 to_run, not_run = [], []
162 169 if not inc_slow:
@@ -164,16 +171,20 b' def prepare_py_test_controllers(inc_slow=False, xunit=False, coverage=False):'
164 171
165 172 for name in test_group_names:
166 173 controller = PyTestController(name)
167 if xunit:
168 controller.add_xunit()
169 if coverage:
170 controller.add_coverage()
171 174 if controller.will_run:
172 175 to_run.append(controller)
173 176 else:
174 177 not_run.append(controller)
175 178 return to_run, not_run
176 179
180 def configure_controllers(controllers, xunit=False, coverage=False):
181 """Apply options for a collection of TestController objects."""
182 for controller in controllers:
183 if xunit:
184 controller.add_xunit()
185 if coverage:
186 controller.add_coverage()
187
177 188 def do_run(controller):
178 189 try:
179 190 try:
@@ -217,7 +228,7 b' def report():'
217 228
218 229 return ''.join(out)
219 230
220 def run_iptestall(inc_slow=False, jobs=1, xunit_out=False, coverage_out=False):
231 def run_iptestall(options):
221 232 """Run the entire IPython test suite by calling nose and trial.
222 233
223 234 This function constructs :class:`IPTester` instances for all IPython
@@ -227,20 +238,39 b' def run_iptestall(inc_slow=False, jobs=1, xunit_out=False, coverage_out=False):'
227 238
228 239 Parameters
229 240 ----------
230
231 inc_slow : bool, optional
241
242 All parameters are passed as attributes of the options object.
243
244 testgroups : list of str
245 Run only these sections of the test suite. If empty, run all the available
246 sections.
247
248 fast : int or None
249 Run the test suite in parallel, using n simultaneous processes. If None
250 is passed, one process is used per CPU core. Default 1 (i.e. sequential)
251
252 inc_slow : bool
232 253 Include slow tests, like IPython.parallel. By default, these tests aren't
233 254 run.
234 255
235 fast : bool, option
236 Run the test suite in parallel, if True, using as many threads as there
237 are processors
256 xunit : bool
257 Produce Xunit XML output. This is written to multiple foo.xunit.xml files.
258
259 coverage : bool or str
260 Measure code coverage from tests. True will store the raw coverage data,
261 or pass 'html' or 'xml' to get reports.
238 262 """
239 if jobs != 1:
263 if options.fast != 1:
264 # If running in parallel, capture output so it doesn't get interleaved
240 265 TestController.buffer_output = True
241 266
242 to_run, not_run = prepare_py_test_controllers(inc_slow=inc_slow, xunit=xunit_out,
243 coverage=coverage_out)
267 if options.testgroups:
268 to_run = [PyTestController(name) for name in options.testgroups]
269 not_run = []
270 else:
271 to_run, not_run = prepare_py_test_controllers(inc_slow=options.all)
272
273 configure_controllers(to_run, xunit=options.xunit, coverage=options.coverage)
244 274
245 275 def justify(ltext, rtext, width=70, fill='-'):
246 276 ltext += ' '
@@ -251,8 +281,9 b' def run_iptestall(inc_slow=False, jobs=1, xunit_out=False, coverage_out=False):'
251 281 failed = []
252 282 t_start = time.time()
253 283
254 print('*'*70)
255 if jobs == 1:
284 print()
285 if options.fast == 1:
286 # This actually means sequential, i.e. with 1 job
256 287 for controller in to_run:
257 288 print('IPython test group:', controller.section)
258 289 controller, res = do_run(controller)
@@ -264,8 +295,9 b' def run_iptestall(inc_slow=False, jobs=1, xunit_out=False, coverage_out=False):'
264 295 print()
265 296
266 297 else:
298 # Run tests concurrently
267 299 try:
268 pool = multiprocessing.pool.ThreadPool(jobs)
300 pool = multiprocessing.pool.ThreadPool(options.fast)
269 301 for (controller, res) in pool.imap_unordered(do_run, to_run):
270 302 res_string = 'OK' if res == 0 else 'FAILED'
271 303 print(justify('IPython test group: ' + controller.section, res_string))
@@ -286,33 +318,33 b' def run_iptestall(inc_slow=False, jobs=1, xunit_out=False, coverage_out=False):'
286 318 nrunners = len(to_run)
287 319 nfail = len(failed)
288 320 # summarize results
289 print('*'*70)
321 print('_'*70)
290 322 print('Test suite completed for system with the following information:')
291 323 print(report())
292 324 print('Ran %s test groups in %.3fs' % (nrunners, t_tests))
293 325 print()
294 print('Status:')
326 print('Status: ', end='')
295 327 if not failed:
296 328 print('OK')
297 329 else:
298 330 # If anything went wrong, point out what command to rerun manually to
299 331 # see the actual errors and individual summary
300 print('ERROR - %s out of %s test groups failed.' % (nfail, nrunners))
301 for controller in failed:
302 print('-'*40)
303 print('Runner failed:', controller.section)
304 print('You may wish to rerun this one individually, with:')
305 print(' iptest', *controller.cmd[3:])
306 print()
307
308 if coverage_out:
332 failed_sections = [c.section for c in failed]
333 print('ERROR - {} out of {} test groups failed ({}).'.format(nfail,
334 nrunners, ', '.join(failed_sections)))
335 print()
336 print('You may wish to rerun these, with:')
337 print(' iptest', *failed_sections)
338 print()
339
340 if options.coverage:
309 341 from coverage import coverage
310 342 cov = coverage(data_file='.coverage')
311 343 cov.combine()
312 344 cov.save()
313 345
314 346 # Coverage HTML report
315 if coverage_out == 'html':
347 if options.coverage == 'html':
316 348 html_dir = 'ipy_htmlcov'
317 349 shutil.rmtree(html_dir, ignore_errors=True)
318 350 print("Writing HTML coverage report to %s/ ... " % html_dir, end="")
@@ -340,7 +372,7 b' def run_iptestall(inc_slow=False, jobs=1, xunit_out=False, coverage_out=False):'
340 372 print('done.')
341 373
342 374 # Coverage XML report
343 elif coverage_out == 'xml':
375 elif options.coverage == 'xml':
344 376 cov.xml_report(outfile='ipy_coverage.xml')
345 377
346 378 if failed:
@@ -349,14 +381,10 b' def run_iptestall(inc_slow=False, jobs=1, xunit_out=False, coverage_out=False):'
349 381
350 382
351 383 def main():
352 if len(sys.argv) > 1 and \
353 ((sys.argv[1] in test_sections) or sys.argv[1].startswith('IPython')):
354 from .iptest import run_iptest
355 # This is in-process
356 run_iptest()
357 return
358
359 384 parser = argparse.ArgumentParser(description='Run IPython test suite')
385 parser.add_argument('testgroups', nargs='*',
386 help='Run specified groups of tests. If omitted, run '
387 'all tests.')
360 388 parser.add_argument('--all', action='store_true',
361 389 help='Include slow tests not run by default.')
362 390 parser.add_argument('-j', '--fast', nargs='?', const=None, default=1,
@@ -370,13 +398,12 b' def main():'
370 398 options = parser.parse_args()
371 399
372 400 try:
373 jobs = int(options.fast)
401 options.fast = int(options.fast)
374 402 except TypeError:
375 jobs = options.fast
403 pass
376 404
377 405 # This starts subprocesses
378 run_iptestall(inc_slow=options.all, jobs=jobs,
379 xunit_out=options.xunit, coverage_out=options.coverage)
406 run_iptestall(options)
380 407
381 408
382 409 if __name__ == '__main__':
General Comments 0
You need to be logged in to leave comments. Login now