Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(201)

Side by Side Diff: third_party/logilab/common/pytest.py

Issue 719313003: Revert "pylint: upgrade to 1.3.1" (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@master
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/logilab/common/pyro_ext.py ('k') | third_party/logilab/common/registry.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. 1 # copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr 2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
3 # 3 #
4 # This file is part of logilab-common. 4 # This file is part of logilab-common.
5 # 5 #
6 # logilab-common is free software: you can redistribute it and/or modify it unde r 6 # logilab-common is free software: you can redistribute it and/or modify it unde r
7 # the terms of the GNU Lesser General Public License as published by the Free 7 # the terms of the GNU Lesser General Public License as published by the Free
8 # Software Foundation, either version 2.1 of the License, or (at your option) an y 8 # Software Foundation, either version 2.1 of the License, or (at your option) an y
9 # later version. 9 # later version.
10 # 10 #
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
85 def titi(test): 85 def titi(test):
86 pass 86 pass
87 87
88 you can filter the function with a simple python expression 88 you can filter the function with a simple python expression
89 89
90 * ``toto`` and ``titi`` match ``rouge`` 90 * ``toto`` and ``titi`` match ``rouge``
91 * ``toto``, ``tata`` and ``titi``, match ``rouge or carre`` 91 * ``toto``, ``tata`` and ``titi``, match ``rouge or carre``
92 * ``tata`` and ``titi`` match``rouge ^ carre`` 92 * ``tata`` and ``titi`` match``rouge ^ carre``
93 * ``titi`` match ``rouge and not carre`` 93 * ``titi`` match ``rouge and not carre``
94 """ 94 """
95
96 from __future__ import print_function
97
98 __docformat__ = "restructuredtext en" 95 __docformat__ = "restructuredtext en"
99 96
100 PYTEST_DOC = """%prog [OPTIONS] [testfile [testpattern]] 97 PYTEST_DOC = """%prog [OPTIONS] [testfile [testpattern]]
101 98
102 examples: 99 examples:
103 100
104 pytest path/to/mytests.py 101 pytest path/to/mytests.py
105 pytest path/to/mytests.py TheseTests 102 pytest path/to/mytests.py TheseTests
106 pytest path/to/mytests.py TheseTests.test_thisone 103 pytest path/to/mytests.py TheseTests.test_thisone
107 pytest path/to/mytests.py -m '(not long and database) or regr' 104 pytest path/to/mytests.py -m '(not long and database) or regr'
108 105
109 pytest one (will run both test_thisone and test_thatone) 106 pytest one (will run both test_thisone and test_thatone)
110 pytest path/to/mytests.py -s not (will skip test_notthisone) 107 pytest path/to/mytests.py -s not (will skip test_notthisone)
108
109 pytest --coverage test_foo.py
110 (only if logilab.devtools is available)
111 """ 111 """
112 112
113 ENABLE_DBC = False 113 ENABLE_DBC = False
114 FILE_RESTART = ".pytest.restart" 114 FILE_RESTART = ".pytest.restart"
115 115
116 import os, sys, re 116 import os, sys, re
117 import os.path as osp 117 import os.path as osp
118 from time import time, clock 118 from time import time, clock
119 import warnings 119 import warnings
120 import types 120 import types
121 from inspect import isgeneratorfunction, isclass
122 121
123 from logilab.common.fileutils import abspath_listdir 122 from logilab.common.fileutils import abspath_listdir
124 from logilab.common import textutils 123 from logilab.common import textutils
125 from logilab.common import testlib, STD_BLACKLIST 124 from logilab.common import testlib, STD_BLACKLIST
126 # use the same unittest module as testlib 125 # use the same unittest module as testlib
127 from logilab.common.testlib import unittest, start_interactive_mode 126 from logilab.common.testlib import unittest, start_interactive_mode
127 from logilab.common.compat import any
128 import doctest 128 import doctest
129 129
130 import unittest as unittest_legacy 130 import unittest as unittest_legacy
131 if not getattr(unittest_legacy, "__package__", None): 131 if not getattr(unittest_legacy, "__package__", None):
132 try: 132 try:
133 import unittest2.suite as unittest_suite 133 import unittest2.suite as unittest_suite
134 except ImportError: 134 except ImportError:
135 sys.exit("You have to install python-unittest2 to use this module") 135 sys.exit("You have to install python-unittest2 to use this module")
136 else: 136 else:
137 import unittest.suite as unittest_suite 137 import unittest.suite as unittest_suite
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 def this_is_a_testdir(dirpath): 199 def this_is_a_testdir(dirpath):
200 """returns True if `filename` seems to be a test directory""" 200 """returns True if `filename` seems to be a test directory"""
201 return TESTDIR_RE.match(osp.basename(dirpath)) 201 return TESTDIR_RE.match(osp.basename(dirpath))
202 202
203 203
204 def load_pytest_conf(path, parser): 204 def load_pytest_conf(path, parser):
205 """loads a ``pytestconf.py`` file and update default parser 205 """loads a ``pytestconf.py`` file and update default parser
206 and / or tester. 206 and / or tester.
207 """ 207 """
208 namespace = {} 208 namespace = {}
209 exec(open(path, 'rb').read(), namespace) 209 execfile(path, namespace)
210 if 'update_parser' in namespace: 210 if 'update_parser' in namespace:
211 namespace['update_parser'](parser) 211 namespace['update_parser'](parser)
212 return namespace.get('CustomPyTester', PyTester) 212 return namespace.get('CustomPyTester', PyTester)
213 213
214 214
215 def project_root(parser, projdir=os.getcwd()): 215 def project_root(parser, projdir=os.getcwd()):
216 """try to find project's root and add it to sys.path""" 216 """try to find project's root and add it to sys.path"""
217 previousdir = curdir = osp.abspath(projdir) 217 previousdir = curdir = osp.abspath(projdir)
218 testercls = PyTester 218 testercls = PyTester
219 conf_file_path = osp.join(curdir, CONF_FILE) 219 conf_file_path = osp.join(curdir, CONF_FILE)
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
302 This is used to avoid strange side-effects when using the 302 This is used to avoid strange side-effects when using the
303 testall() mode of pytest. 303 testall() mode of pytest.
304 For instance, if we run pytest on this tree:: 304 For instance, if we run pytest on this tree::
305 305
306 A/test/test_utils.py 306 A/test/test_utils.py
307 B/test/test_utils.py 307 B/test/test_utils.py
308 308
309 we **have** to clean sys.modules to make sure the correct test_utils 309 we **have** to clean sys.modules to make sure the correct test_utils
310 module is ran in B 310 module is ran in B
311 """ 311 """
312 for modname, mod in list(sys.modules.items()): 312 for modname, mod in sys.modules.items():
313 if mod is None: 313 if mod is None:
314 continue 314 continue
315 if not hasattr(mod, '__file__'): 315 if not hasattr(mod, '__file__'):
316 # this is the case of some built-in modules like sys, imp, marshal 316 # this is the case of some built-in modules like sys, imp, marshal
317 continue 317 continue
318 modfile = mod.__file__ 318 modfile = mod.__file__
319 # if modfile is not an absolute path, it was probably loaded locally 319 # if modfile is not an absolute path, it was probably loaded locally
320 # during the tests 320 # during the tests
321 if not osp.isabs(modfile) or modfile.startswith(testdir): 321 if not osp.isabs(modfile) or modfile.startswith(testdir):
322 del sys.modules[modname] 322 del sys.modules[modname]
323 323
324 324
325 325
326 class PyTester(object): 326 class PyTester(object):
327 """encapsulates testrun logic""" 327 """encapsulates testrun logic"""
328 328
329 def __init__(self, cvg, options): 329 def __init__(self, cvg, options):
330 self.report = GlobalTestReport() 330 self.report = GlobalTestReport()
331 self.cvg = cvg 331 self.cvg = cvg
332 self.options = options 332 self.options = options
333 self.firstwrite = True 333 self.firstwrite = True
334 self._errcode = None 334 self._errcode = None
335 335
336 def show_report(self): 336 def show_report(self):
337 """prints the report and returns appropriate exitcode""" 337 """prints the report and returns appropriate exitcode"""
338 # everything has been ran, print report 338 # everything has been ran, print report
339 print("*" * 79) 339 print "*" * 79
340 print(self.report) 340 print self.report
341 341
342 def get_errcode(self): 342 def get_errcode(self):
343 # errcode set explicitly 343 # errcode set explicitly
344 if self._errcode is not None: 344 if self._errcode is not None:
345 return self._errcode 345 return self._errcode
346 return self.report.failures + self.report.errors 346 return self.report.failures + self.report.errors
347 347
348 def set_errcode(self, errcode): 348 def set_errcode(self, errcode):
349 self._errcode = errcode 349 self._errcode = errcode
350 errcode = property(get_errcode, set_errcode) 350 errcode = property(get_errcode, set_errcode)
351 351
352 def testall(self, exitfirst=False): 352 def testall(self, exitfirst=False):
353 """walks through current working directory, finds something 353 """walks through current working directory, finds something
354 which can be considered as a testdir and runs every test there 354 which can be considered as a testdir and runs every test there
355 """ 355 """
356 here = os.getcwd() 356 here = os.getcwd()
357 for dirname, dirs, _ in os.walk(here): 357 for dirname, dirs, _ in os.walk(here):
358 for skipped in STD_BLACKLIST: 358 for skipped in STD_BLACKLIST:
359 if skipped in dirs: 359 if skipped in dirs:
360 dirs.remove(skipped) 360 dirs.remove(skipped)
361 basename = osp.basename(dirname) 361 basename = osp.basename(dirname)
362 if this_is_a_testdir(basename): 362 if this_is_a_testdir(basename):
363 print("going into", dirname) 363 print "going into", dirname
364 # we found a testdir, let's explore it ! 364 # we found a testdir, let's explore it !
365 if not self.testonedir(dirname, exitfirst): 365 if not self.testonedir(dirname, exitfirst):
366 break 366 break
367 dirs[:] = [] 367 dirs[:] = []
368 if self.report.ran == 0: 368 if self.report.ran == 0:
369 print("no test dir found testing here:", here) 369 print "no test dir found testing here:", here
370 # if no test was found during the visit, consider 370 # if no test was found during the visit, consider
371 # the local directory as a test directory even if 371 # the local directory as a test directory even if
372 # it doesn't have a traditional test directory name 372 # it doesn't have a traditional test directory name
373 self.testonedir(here) 373 self.testonedir(here)
374 374
375 def testonedir(self, testdir, exitfirst=False): 375 def testonedir(self, testdir, exitfirst=False):
376 """finds each testfile in the `testdir` and runs it 376 """finds each testfile in the `testdir` and runs it
377 377
378 return true when all tests has been executed, false if exitfirst and 378 return true when all tests has been executed, false if exitfirst and
379 some test has failed. 379 some test has failed.
380 """ 380 """
381 for filename in abspath_listdir(testdir): 381 for filename in abspath_listdir(testdir):
382 if this_is_a_testfile(filename): 382 if this_is_a_testfile(filename):
383 if self.options.exitfirst and not self.options.restart: 383 if self.options.exitfirst and not self.options.restart:
384 # overwrite restart file 384 # overwrite restart file
385 try: 385 try:
386 restartfile = open(FILE_RESTART, "w") 386 restartfile = open(FILE_RESTART, "w")
387 restartfile.close() 387 restartfile.close()
388 except Exception: 388 except Exception, e:
389 print("Error while overwriting succeeded test file :", 389 print >> sys.__stderr__, "Error while overwriting \
390 osp.join(os.getcwd(), FILE_RESTART), 390 succeeded test file :", osp.join(os.getcwd(), FILE_RESTART)
391 file=sys.__stderr__) 391 raise e
392 raise
393 # run test and collect information 392 # run test and collect information
394 prog = self.testfile(filename, batchmode=True) 393 prog = self.testfile(filename, batchmode=True)
395 if exitfirst and (prog is None or not prog.result.wasSuccessful( )): 394 if exitfirst and (prog is None or not prog.result.wasSuccessful( )):
396 return False 395 return False
397 self.firstwrite = True 396 self.firstwrite = True
398 # clean local modules 397 # clean local modules
399 remove_local_modules_from_sys(testdir) 398 remove_local_modules_from_sys(testdir)
400 return True 399 return True
401 400
402 def testfile(self, filename, batchmode=False): 401 def testfile(self, filename, batchmode=False):
403 """runs every test in `filename` 402 """runs every test in `filename`
404 403
405 :param filename: an absolute path pointing to a unittest file 404 :param filename: an absolute path pointing to a unittest file
406 """ 405 """
407 here = os.getcwd() 406 here = os.getcwd()
408 dirname = osp.dirname(filename) 407 dirname = osp.dirname(filename)
409 if dirname: 408 if dirname:
410 os.chdir(dirname) 409 os.chdir(dirname)
411 # overwrite restart file if it has not been done already 410 # overwrite restart file if it has not been done already
412 if self.options.exitfirst and not self.options.restart and self.firstwri te: 411 if self.options.exitfirst and not self.options.restart and self.firstwri te:
413 try: 412 try:
414 restartfile = open(FILE_RESTART, "w") 413 restartfile = open(FILE_RESTART, "w")
415 restartfile.close() 414 restartfile.close()
416 except Exception: 415 except Exception, e:
417 print("Error while overwriting succeeded test file :", 416 print >> sys.__stderr__, "Error while overwriting \
418 osp.join(os.getcwd(), FILE_RESTART), file=sys.__stderr__) 417 succeeded test file :", osp.join(os.getcwd(), FILE_RESTART)
419 raise 418 raise e
420 modname = osp.basename(filename)[:-3] 419 modname = osp.basename(filename)[:-3]
421 print((' %s ' % osp.basename(filename)).center(70, '='), 420 try:
422 file=sys.__stderr__) 421 print >> sys.stderr, (' %s ' % osp.basename(filename)).center(70, '=')
422 except TypeError: # < py 2.4 bw compat
423 print >> sys.stderr, (' %s ' % osp.basename(filename)).center(70)
423 try: 424 try:
424 tstart, cstart = time(), clock() 425 tstart, cstart = time(), clock()
425 try: 426 try:
426 testprog = SkipAwareTestProgram(modname, batchmode=batchmode, cv g=self.cvg, 427 testprog = SkipAwareTestProgram(modname, batchmode=batchmode, cv g=self.cvg,
427 options=self.options, outstream =sys.stderr) 428 options=self.options, outstream =sys.stderr)
428 except KeyboardInterrupt: 429 except KeyboardInterrupt:
429 raise 430 raise
430 except SystemExit as exc: 431 except SystemExit, exc:
431 self.errcode = exc.code 432 self.errcode = exc.code
432 raise 433 raise
433 except testlib.SkipTest: 434 except testlib.SkipTest:
434 print("Module skipped:", filename) 435 print "Module skipped:", filename
435 self.report.skip_module(filename) 436 self.report.skip_module(filename)
436 return None 437 return None
437 except Exception: 438 except Exception:
438 self.report.failed_to_test_module(filename) 439 self.report.failed_to_test_module(filename)
439 print('unhandled exception occurred while testing', modname, 440 print >> sys.stderr, 'unhandled exception occurred while testing ', modname
440 file=sys.stderr)
441 import traceback 441 import traceback
442 traceback.print_exc(file=sys.stderr) 442 traceback.print_exc(file=sys.stderr)
443 return None 443 return None
444 444
445 tend, cend = time(), clock() 445 tend, cend = time(), clock()
446 ttime, ctime = (tend - tstart), (cend - cstart) 446 ttime, ctime = (tend - tstart), (cend - cstart)
447 self.report.feed(filename, testprog.result, ttime, ctime) 447 self.report.feed(filename, testprog.result, ttime, ctime)
448 return testprog 448 return testprog
449 finally: 449 finally:
450 if dirname: 450 if dirname:
(...skipping 30 matching lines...) Expand all
481 from django.test.utils import create_test_db 481 from django.test.utils import create_test_db
482 setup_test_environment() 482 setup_test_environment()
483 create_test_db(verbosity=0) 483 create_test_db(verbosity=0)
484 self.dbname = self.settings.TEST_DATABASE_NAME 484 self.dbname = self.settings.TEST_DATABASE_NAME
485 485
486 def after_testfile(self): 486 def after_testfile(self):
487 # Those imports must be done **after** setup_environ was called 487 # Those imports must be done **after** setup_environ was called
488 from django.test.utils import teardown_test_environment 488 from django.test.utils import teardown_test_environment
489 from django.test.utils import destroy_test_db 489 from django.test.utils import destroy_test_db
490 teardown_test_environment() 490 teardown_test_environment()
491 print('destroying', self.dbname) 491 print 'destroying', self.dbname
492 destroy_test_db(self.dbname, verbosity=0) 492 destroy_test_db(self.dbname, verbosity=0)
493 493
494 def testall(self, exitfirst=False): 494 def testall(self, exitfirst=False):
495 """walks through current working directory, finds something 495 """walks through current working directory, finds something
496 which can be considered as a testdir and runs every test there 496 which can be considered as a testdir and runs every test there
497 """ 497 """
498 for dirname, dirs, files in os.walk(os.getcwd()): 498 for dirname, dirs, files in os.walk(os.getcwd()):
499 for skipped in ('CVS', '.svn', '.hg'): 499 for skipped in ('CVS', '.svn', '.hg'):
500 if skipped in dirs: 500 if skipped in dirs:
501 dirs.remove(skipped) 501 dirs.remove(skipped)
502 if 'tests.py' in files: 502 if 'tests.py' in files:
503 if not self.testonedir(dirname, exitfirst): 503 if not self.testonedir(dirname, exitfirst):
504 break 504 break
505 dirs[:] = [] 505 dirs[:] = []
506 else: 506 else:
507 basename = osp.basename(dirname) 507 basename = osp.basename(dirname)
508 if basename in ('test', 'tests'): 508 if basename in ('test', 'tests'):
509 print("going into", dirname) 509 print "going into", dirname
510 # we found a testdir, let's explore it ! 510 # we found a testdir, let's explore it !
511 if not self.testonedir(dirname, exitfirst): 511 if not self.testonedir(dirname, exitfirst):
512 break 512 break
513 dirs[:] = [] 513 dirs[:] = []
514 514
515 def testonedir(self, testdir, exitfirst=False): 515 def testonedir(self, testdir, exitfirst=False):
516 """finds each testfile in the `testdir` and runs it 516 """finds each testfile in the `testdir` and runs it
517 517
518 return true when all tests has been executed, false if exitfirst and 518 return true when all tests has been executed, false if exitfirst and
519 some test has failed. 519 some test has failed.
(...skipping 20 matching lines...) Expand all
540 """runs every test in `filename` 540 """runs every test in `filename`
541 541
542 :param filename: an absolute path pointing to a unittest file 542 :param filename: an absolute path pointing to a unittest file
543 """ 543 """
544 here = os.getcwd() 544 here = os.getcwd()
545 dirname = osp.dirname(filename) 545 dirname = osp.dirname(filename)
546 if dirname: 546 if dirname:
547 os.chdir(dirname) 547 os.chdir(dirname)
548 self.load_django_settings(dirname) 548 self.load_django_settings(dirname)
549 modname = osp.basename(filename)[:-3] 549 modname = osp.basename(filename)[:-3]
550 print((' %s ' % osp.basename(filename)).center(70, '='), 550 print >>sys.stderr, (' %s ' % osp.basename(filename)).center(70, '=')
551 file=sys.stderr)
552 try: 551 try:
553 try: 552 try:
554 tstart, cstart = time(), clock() 553 tstart, cstart = time(), clock()
555 self.before_testfile() 554 self.before_testfile()
556 testprog = SkipAwareTestProgram(modname, batchmode=batchmode, cv g=self.cvg) 555 testprog = SkipAwareTestProgram(modname, batchmode=batchmode, cv g=self.cvg)
557 tend, cend = time(), clock() 556 tend, cend = time(), clock()
558 ttime, ctime = (tend - tstart), (cend - cstart) 557 ttime, ctime = (tend - tstart), (cend - cstart)
559 self.report.feed(filename, testprog.result, ttime, ctime) 558 self.report.feed(filename, testprog.result, ttime, ctime)
560 return testprog 559 return testprog
561 except SystemExit: 560 except SystemExit:
562 raise 561 raise
563 except Exception as exc: 562 except Exception, exc:
564 import traceback 563 import traceback
565 traceback.print_exc() 564 traceback.print_exc()
566 self.report.failed_to_test_module(filename) 565 self.report.failed_to_test_module(filename)
567 print('unhandled exception occurred while testing', modname) 566 print 'unhandled exception occurred while testing', modname
568 print('error: %s' % exc) 567 print 'error: %s' % exc
569 return None 568 return None
570 finally: 569 finally:
571 self.after_testfile() 570 self.after_testfile()
572 if dirname: 571 if dirname:
573 os.chdir(here) 572 os.chdir(here)
574 573
575 574
576 def make_parser(): 575 def make_parser():
577 """creates the OptionParser instance 576 """creates the OptionParser instance
578 """ 577 """
(...skipping 19 matching lines...) Expand all
598 # pytest options 597 # pytest options
599 parser.add_option('-t', dest='testdir', default=None, 598 parser.add_option('-t', dest='testdir', default=None,
600 help="directory where the tests will be found") 599 help="directory where the tests will be found")
601 parser.add_option('-d', dest='dbc', default=False, 600 parser.add_option('-d', dest='dbc', default=False,
602 action="store_true", help="enable design-by-contract") 601 action="store_true", help="enable design-by-contract")
603 # unittest_main options provided and passed through pytest 602 # unittest_main options provided and passed through pytest
604 parser.add_option('-v', '--verbose', callback=rebuild_cmdline, 603 parser.add_option('-v', '--verbose', callback=rebuild_cmdline,
605 action="callback", help="Verbose output") 604 action="callback", help="Verbose output")
606 parser.add_option('-i', '--pdb', callback=rebuild_and_store, 605 parser.add_option('-i', '--pdb', callback=rebuild_and_store,
607 dest="pdb", action="callback", 606 dest="pdb", action="callback",
608 help="Enable test failure inspection") 607 help="Enable test failure inspection (conflicts with --cov erage)")
609 parser.add_option('-x', '--exitfirst', callback=rebuild_and_store, 608 parser.add_option('-x', '--exitfirst', callback=rebuild_and_store,
610 dest="exitfirst", default=False, 609 dest="exitfirst", default=False,
611 action="callback", help="Exit on first failure " 610 action="callback", help="Exit on first failure "
612 "(only make sense when pytest run one test file)") 611 "(only make sense when pytest run one test file)")
613 parser.add_option('-R', '--restart', callback=rebuild_and_store, 612 parser.add_option('-R', '--restart', callback=rebuild_and_store,
614 dest="restart", default=False, 613 dest="restart", default=False,
615 action="callback", 614 action="callback",
616 help="Restart tests from where it failed (implies exitfirs t) " 615 help="Restart tests from where it failed (implies exitfirs t) "
617 "(only make sense if tests previously ran with exitfirst only)") 616 "(only make sense if tests previously ran with exitfirst only)")
618 parser.add_option('--color', callback=rebuild_cmdline, 617 parser.add_option('--color', callback=rebuild_cmdline,
619 action="callback", 618 action="callback",
620 help="colorize tracebacks") 619 help="colorize tracebacks")
621 parser.add_option('-s', '--skip', 620 parser.add_option('-s', '--skip',
622 # XXX: I wish I could use the callback action but it 621 # XXX: I wish I could use the callback action but it
623 # doesn't seem to be able to get the value 622 # doesn't seem to be able to get the value
624 # associated to the option 623 # associated to the option
625 action="store", dest="skipped", default=None, 624 action="store", dest="skipped", default=None,
626 help="test names matching this name will be skipped " 625 help="test names matching this name will be skipped "
627 "to skip several patterns, use commas") 626 "to skip several patterns, use commas")
628 parser.add_option('-q', '--quiet', callback=rebuild_cmdline, 627 parser.add_option('-q', '--quiet', callback=rebuild_cmdline,
629 action="callback", help="Minimal output") 628 action="callback", help="Minimal output")
630 parser.add_option('-P', '--profile', default=None, dest='profile', 629 parser.add_option('-P', '--profile', default=None, dest='profile',
631 help="Profile execution and store data in the given file") 630 help="Profile execution and store data in the given file")
632 parser.add_option('-m', '--match', default=None, dest='tags_pattern', 631 parser.add_option('-m', '--match', default=None, dest='tags_pattern',
633 help="only execute test whose tag match the current patter n") 632 help="only execute test whose tag match the current patter n")
634 633
634 try:
635 from logilab.devtools.lib.coverage import Coverage
636 parser.add_option('--coverage', dest="coverage", default=False,
637 action="store_true",
638 help="run tests with pycoverage (conflicts with --pdb) ")
639 except ImportError:
640 pass
641
635 if DJANGO_FOUND: 642 if DJANGO_FOUND:
636 parser.add_option('-J', '--django', dest='django', default=False, 643 parser.add_option('-J', '--django', dest='django', default=False,
637 action="store_true", 644 action="store_true",
638 help='use pytest for django test cases') 645 help='use pytest for django test cases')
639 return parser 646 return parser
640 647
641 648
642 def parseargs(parser): 649 def parseargs(parser):
643 """Parse the command line and return (options processed), (options to pass t o 650 """Parse the command line and return (options processed), (options to pass t o
644 unittest_main()), (explicitfile or None). 651 unittest_main()), (explicitfile or None).
645 """ 652 """
646 # parse the command line 653 # parse the command line
647 options, args = parser.parse_args() 654 options, args = parser.parse_args()
655 if options.pdb and getattr(options, 'coverage', False):
656 parser.error("'pdb' and 'coverage' options are exclusive")
648 filenames = [arg for arg in args if arg.endswith('.py')] 657 filenames = [arg for arg in args if arg.endswith('.py')]
649 if filenames: 658 if filenames:
650 if len(filenames) > 1: 659 if len(filenames) > 1:
651 parser.error("only one filename is acceptable") 660 parser.error("only one filename is acceptable")
652 explicitfile = filenames[0] 661 explicitfile = filenames[0]
653 args.remove(explicitfile) 662 args.remove(explicitfile)
654 else: 663 else:
655 explicitfile = None 664 explicitfile = None
656 # someone wants DBC 665 # someone wants DBC
657 testlib.ENABLE_DBC = options.dbc 666 testlib.ENABLE_DBC = options.dbc
658 newargs = parser.newargs 667 newargs = parser.newargs
659 if options.skipped: 668 if options.skipped:
660 newargs.extend(['--skip', options.skipped]) 669 newargs.extend(['--skip', options.skipped])
661 # restart implies exitfirst 670 # restart implies exitfirst
662 if options.restart: 671 if options.restart:
663 options.exitfirst = True 672 options.exitfirst = True
664 # append additional args to the new sys.argv and let unittest_main 673 # append additional args to the new sys.argv and let unittest_main
665 # do the rest 674 # do the rest
666 newargs += args 675 newargs += args
667 return options, explicitfile 676 return options, explicitfile
668 677
669 678
670 679
671 def run(): 680 def run():
672 parser = make_parser() 681 parser = make_parser()
673 rootdir, testercls = project_root(parser) 682 rootdir, testercls = project_root(parser)
674 options, explicitfile = parseargs(parser) 683 options, explicitfile = parseargs(parser)
675 # mock a new command line 684 # mock a new command line
676 sys.argv[1:] = parser.newargs 685 sys.argv[1:] = parser.newargs
686 covermode = getattr(options, 'coverage', None)
677 cvg = None 687 cvg = None
678 if not '' in sys.path: 688 if not '' in sys.path:
679 sys.path.insert(0, '') 689 sys.path.insert(0, '')
690 if covermode:
691 # control_import_coverage(rootdir)
692 from logilab.devtools.lib.coverage import Coverage
693 cvg = Coverage([rootdir])
694 cvg.erase()
695 cvg.start()
680 if DJANGO_FOUND and options.django: 696 if DJANGO_FOUND and options.django:
681 tester = DjangoTester(cvg, options) 697 tester = DjangoTester(cvg, options)
682 else: 698 else:
683 tester = testercls(cvg, options) 699 tester = testercls(cvg, options)
684 if explicitfile: 700 if explicitfile:
685 cmd, args = tester.testfile, (explicitfile,) 701 cmd, args = tester.testfile, (explicitfile,)
686 elif options.testdir: 702 elif options.testdir:
687 cmd, args = tester.testonedir, (options.testdir, options.exitfirst) 703 cmd, args = tester.testonedir, (options.testdir, options.exitfirst)
688 else: 704 else:
689 cmd, args = tester.testall, (options.exitfirst,) 705 cmd, args = tester.testall, (options.exitfirst,)
690 try: 706 try:
691 try: 707 try:
692 if options.profile: 708 if options.profile:
693 import hotshot 709 import hotshot
694 prof = hotshot.Profile(options.profile) 710 prof = hotshot.Profile(options.profile)
695 prof.runcall(cmd, *args) 711 prof.runcall(cmd, *args)
696 prof.close() 712 prof.close()
697 print('profile data saved in', options.profile) 713 print 'profile data saved in', options.profile
698 else: 714 else:
699 cmd(*args) 715 cmd(*args)
700 except SystemExit: 716 except SystemExit:
701 raise 717 raise
702 except: 718 except:
703 import traceback 719 import traceback
704 traceback.print_exc() 720 traceback.print_exc()
705 finally: 721 finally:
722 if covermode:
723 cvg.stop()
724 cvg.save()
706 tester.show_report() 725 tester.show_report()
726 if covermode:
727 print 'coverage information stored, use it with pycoverage -ra'
707 sys.exit(tester.errcode) 728 sys.exit(tester.errcode)
708 729
709 class SkipAwareTestProgram(unittest.TestProgram): 730 class SkipAwareTestProgram(unittest.TestProgram):
710 # XXX: don't try to stay close to unittest.py, use optparse 731 # XXX: don't try to stay close to unittest.py, use optparse
711 USAGE = """\ 732 USAGE = """\
712 Usage: %(progName)s [options] [test] [...] 733 Usage: %(progName)s [options] [test] [...]
713 734
714 Options: 735 Options:
715 -h, --help Show this message 736 -h, --help Show this message
716 -v, --verbose Verbose output 737 -v, --verbose Verbose output
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
788 self.test = self.module.suite() 809 self.test = self.module.suite()
789 else: 810 else:
790 self.test = self.testLoader.loadTestsFromModule(self.module) 811 self.test = self.testLoader.loadTestsFromModule(self.module)
791 return 812 return
792 if len(args) > 0: 813 if len(args) > 0:
793 self.test_pattern = args[0] 814 self.test_pattern = args[0]
794 self.testNames = args 815 self.testNames = args
795 else: 816 else:
796 self.testNames = (self.defaultTest, ) 817 self.testNames = (self.defaultTest, )
797 self.createTests() 818 self.createTests()
798 except getopt.error as msg: 819 except getopt.error, msg:
799 self.usageExit(msg) 820 self.usageExit(msg)
800 821
801 def runTests(self): 822 def runTests(self):
802 if self.profile_name: 823 if self.profile_name:
803 import cProfile 824 import cProfile
804 cProfile.runctx('self._runTests()', globals(), locals(), self.profil e_name ) 825 cProfile.runctx('self._runTests()', globals(), locals(), self.profil e_name )
805 else: 826 else:
806 return self._runTests() 827 return self._runTests()
807 828
808 def _runTests(self): 829 def _runTests(self):
(...skipping 28 matching lines...) Expand all
837 if getattr(self.options, 'restart', False): 858 if getattr(self.options, 'restart', False):
838 # retrieve succeeded tests from FILE_RESTART 859 # retrieve succeeded tests from FILE_RESTART
839 try: 860 try:
840 restartfile = open(FILE_RESTART, 'r') 861 restartfile = open(FILE_RESTART, 'r')
841 try: 862 try:
842 succeededtests = list(elem.rstrip('\n\r') for elem in 863 succeededtests = list(elem.rstrip('\n\r') for elem in
843 restartfile.readlines()) 864 restartfile.readlines())
844 removeSucceededTests(self.test, succeededtests) 865 removeSucceededTests(self.test, succeededtests)
845 finally: 866 finally:
846 restartfile.close() 867 restartfile.close()
847 except Exception as ex: 868 except Exception, ex:
848 raise Exception("Error while reading succeeded tests into %s: %s " 869 raise Exception("Error while reading succeeded tests into %s: %s "
849 % (osp.join(os.getcwd(), FILE_RESTART), ex)) 870 % (osp.join(os.getcwd(), FILE_RESTART), ex))
850 871
851 result = self.testRunner.run(self.test) 872 result = self.testRunner.run(self.test)
852 # help garbage collection: we want TestSuite, which hold refs to every 873 # help garbage collection: we want TestSuite, which hold refs to every
853 # executed TestCase, to be gc'ed 874 # executed TestCase, to be gc'ed
854 del self.test 875 del self.test
855 if getattr(result, "debuggers", None) and \ 876 if getattr(result, "debuggers", None) and \
856 getattr(self, "pdbmode", None): 877 getattr(self, "pdbmode", None):
857 start_interactive_mode(result) 878 start_interactive_mode(result)
(...skipping 21 matching lines...) Expand all
879 900
880 def _this_is_skipped(self, testedname): 901 def _this_is_skipped(self, testedname):
881 return any([(pat in testedname) for pat in self.skipped_patterns]) 902 return any([(pat in testedname) for pat in self.skipped_patterns])
882 903
883 def _runcondition(self, test, skipgenerator=True): 904 def _runcondition(self, test, skipgenerator=True):
884 if isinstance(test, testlib.InnerTest): 905 if isinstance(test, testlib.InnerTest):
885 testname = test.name 906 testname = test.name
886 else: 907 else:
887 if isinstance(test, testlib.TestCase): 908 if isinstance(test, testlib.TestCase):
888 meth = test._get_test_method() 909 meth = test._get_test_method()
889 testname = '%s.%s' % (test.__name__, meth.__name__) 910 func = meth.im_func
911 testname = '%s.%s' % (meth.im_class.__name__, func.__name__)
890 elif isinstance(test, types.FunctionType): 912 elif isinstance(test, types.FunctionType):
891 func = test 913 func = test
892 testname = func.__name__ 914 testname = func.__name__
893 elif isinstance(test, types.MethodType): 915 elif isinstance(test, types.MethodType):
894 cls = test.__self__.__class__ 916 func = test.im_func
895 testname = '%s.%s' % (cls.__name__, test.__name__) 917 testname = '%s.%s' % (test.im_class.__name__, func.__name__)
896 else: 918 else:
897 return True # Not sure when this happens 919 return True # Not sure when this happens
898 if isgeneratorfunction(test) and skipgenerator: 920 if testlib.is_generator(test) and skipgenerator:
899 return self.does_match_tags(test) # Let inner tests decide at ru n time 921 return self.does_match_tags(test) # Let inner tests decide at ru n time
900 if self._this_is_skipped(testname): 922 if self._this_is_skipped(testname):
901 return False # this was explicitly skipped 923 return False # this was explicitly skipped
902 if self.test_pattern is not None: 924 if self.test_pattern is not None:
903 try: 925 try:
904 classpattern, testpattern = self.test_pattern.split('.') 926 classpattern, testpattern = self.test_pattern.split('.')
905 klass, name = testname.split('.') 927 klass, name = testname.split('.')
906 if classpattern not in klass or testpattern not in name: 928 if classpattern not in klass or testpattern not in name:
907 return False 929 return False
908 except ValueError: 930 except ValueError:
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
996 # and to provide callable capability 1018 # and to provide callable capability
997 def loadTestsFromNames(self, names, module=None): 1019 def loadTestsFromNames(self, names, module=None):
998 suites = [] 1020 suites = []
999 for name in names: 1021 for name in names:
1000 suites.extend(self.loadTestsFromName(name, module)) 1022 suites.extend(self.loadTestsFromName(name, module))
1001 return self.suiteClass(suites) 1023 return self.suiteClass(suites)
1002 1024
1003 def _collect_tests(self, module): 1025 def _collect_tests(self, module):
1004 tests = {} 1026 tests = {}
1005 for obj in vars(module).values(): 1027 for obj in vars(module).values():
1006 if isclass(obj) and issubclass(obj, unittest.TestCase): 1028 if (issubclass(type(obj), (types.ClassType, type)) and
1029 issubclass(obj, unittest.TestCase)):
1007 classname = obj.__name__ 1030 classname = obj.__name__
1008 if classname[0] == '_' or self._this_is_skipped(classname): 1031 if classname[0] == '_' or self._this_is_skipped(classname):
1009 continue 1032 continue
1010 methodnames = [] 1033 methodnames = []
1011 # obj is a TestCase class 1034 # obj is a TestCase class
1012 for attrname in dir(obj): 1035 for attrname in dir(obj):
1013 if attrname.startswith(self.testMethodPrefix): 1036 if attrname.startswith(self.testMethodPrefix):
1014 attr = getattr(obj, attrname) 1037 attr = getattr(obj, attrname)
1015 if callable(attr): 1038 if callable(attr):
1016 methodnames.append(attrname) 1039 methodnames.append(attrname)
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
1145 1168
1146 if sys.version_info >= (2, 4): 1169 if sys.version_info >= (2, 4):
1147 doctest.DocTestCase.__bases__ = (testlib.TestCase,) 1170 doctest.DocTestCase.__bases__ = (testlib.TestCase,)
1148 # XXX check python2.6 compatibility 1171 # XXX check python2.6 compatibility
1149 #doctest.DocTestCase._cleanups = [] 1172 #doctest.DocTestCase._cleanups = []
1150 #doctest.DocTestCase._out = [] 1173 #doctest.DocTestCase._out = []
1151 else: 1174 else:
1152 unittest.FunctionTestCase.__bases__ = (testlib.TestCase,) 1175 unittest.FunctionTestCase.__bases__ = (testlib.TestCase,)
1153 unittest.TestSuite.run = _ts_run 1176 unittest.TestSuite.run = _ts_run
1154 unittest.TestSuite._wrapped_run = _ts_wrapped_run 1177 unittest.TestSuite._wrapped_run = _ts_wrapped_run
OLDNEW
« no previous file with comments | « third_party/logilab/common/pyro_ext.py ('k') | third_party/logilab/common/registry.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698