Changeset 23

Show
Ignore:
Timestamp:
Sun Apr 16 12:58:40 2006
Author:
jpellerin
Message:
  • Unittest compat updates (#34, #36)
  • Add stop on first error option (#40)
  • Fix core test that was breaking profiler (#41)
  • Fix handling of file name comparisons when the wanted or candidate file is a .pyc/.pyo file (#42)
  • Bail early if wanted file doesn't exist (#43)


Files:

Legend:

Unmodified
Added
Removed
Modified
  • trunk/unit_tests/test_loader.py

    r21 r23  
    1 1 import os  
      2 import sys  
    2 3 import unittest  
    3 4 from nose import case, loader  
    4 5 from nose.config import Config  
      6 from nose.importer import _import  
    5 7  
    6 8 from mock import *  
     
    54 56         l = loader.TestLoader(c)  
    55 57  
      58         foo = _import('foo', [self.support], c)  
      59          
    56 60         expect = [ 'test module test in %s' % self.support,  
    57                      'test module foo.test in %s' % self.support ]  
      61                    'test module foo.test_foo in %s' % self.support ]  
    57 61         found = []  
    58           tests = l.loadTestsFromNames(['test', 'foo.test'])  
    59           for t in tests:             
    60               found.append(str(t))  
    61           self.assertEqual(found, expect)  
    62    
    63           expect = [ 'test module foo.test in %s' % self.support ]  
    64           found = []  
    65           tests = l.loadTestsFromNames(['test'], module='foo')  
      62         tests = l.loadTestsFromNames(['test', 'foo.test_foo'])  
    66 63         for t in tests:             
    67 64             found.append(str(t))  
     
    70 67          
    71 68         expect = [ 'test module foo in %s' % self.support ]  
    72           found = []  
    73           tests = l.loadTestsFromNames(None, module='foo')         
    74           for t in tests:  
    75               found.append(str(t))  
      69         # found = []  
      70         tests = l.loadTestsFromNames(None, module=foo)  
      71         found = [ str(tests) ]  
      72         #for t in tests:  
      73         #    found.append(str(t))  
    76 74         self.assertEqual(found, expect)  
    77 75  
      76         #found = []  
      77         #Etests = l.loadTestsFromNames(None, module=foo)  
      78         #Efor t in tests:  
      79         #    found.append(str(t))  
      80         #self.assertEqual(found, expect)  
      81  
      82     def test_load_from_names_compat(self):  
      83         c = Config()  
      84         l = loader.TestLoader(c)  
      85          
      86         # implicit : prepended when module specified  
      87         names = ['TestNoseTestLoader.test_load_from_names_compat']  
      88         tests = l.loadTestsFromNames(names, sys.modules[__name__])  
      89  
      90         # should be... me  
      91         expect = [ 'test_load_from_names_compat '  
      92                    '(%s.TestNoseTestLoader)' % __name__ ]  
      93         found = []  
      94         # print tests  
      95         for test in tests:  
      96             # print test  
      97             for t in test:  
      98                 # print t  
      99                 found.append(str(t))  
      100         self.assertEqual(found, expect)  
      101                  
      102         # explict : ok too  
      103         c.tests = []  
    78 104         found = []  
    79           tests = l.loadTestsFromNames(None, module='foo')         
    80           for t in tests:  
    81               found.append(str(t))  
      105         names[0] = ':' + names[0]  
      106         tests = l.loadTestsFromNames(names, sys.modules[__name__])  
      107         for test in tests:  
      108             for t in test:  
      109                 found.append(str(t))  
    82 110         self.assertEqual(found, expect)  
    83    
      111          
    83 111     def test_load_from_class(self):  
    84 112         c = Config()  
     
    174 202     logging.basicConfig()  
    175 203     logging.getLogger('').setLevel(0)  
    176       unittest.main() # FIXME testLoader=loader.TestLoader())  
      204     unittest.main() # testLoader=loader.TestLoader())  
  • trunk/unit_tests/test_result.py

    r21 r23  
    105 105         tr.startTest(test)  
    106 106         tr.stopTest(test)  
      107  
      108     def test_stop_on_error(self):  
      109         buf, tr = self.buf, self.tr  
      110         tr.conf.stopOnError = True  
      111         try:  
      112             raise Exception("oh no!")  
      113         except:  
      114             err = sys.exc_info()             
      115         test = self.T()  
      116         tr.addError(test, err)         
      117         self.assertTrue(tr.shouldStop)  
      118  
      119     def test_stop_on_error_fail(self):  
      120         buf, tr = self.buf, self.tr  
      121         tr.conf.stopOnError = True  
      122         try:  
      123             assert False, "test add fail"  
      124         except:  
      125             err = sys.exc_info()             
      126         test = self.T()  
      127         tr.addFailure(test, err)         
      128         self.assertTrue(tr.shouldStop)         
    107 129          
    108 130 if __name__ == '__main__':  
  • trunk/unit_tests/test_plugins.py

    r21 r23  
    62 62         assert plug.tolist('foo') == ['foo']  
    63 63         assert plug.tolist(['foo', 'bar']) == ['foo', 'bar']  
      64         assert plug.tolist('foo,bar') == ['foo', 'bar']  
      65         self.assertEqual(plug.tolist('.*foo/.*,.1'), ['.*foo/.*', '.1'])  
    64 66          
    65 67 class TestDoctestPlugin(unittest.TestCase):  
     
    239 241         plug = MissedTests()  
    240 242  
      243         here = os.path.abspath(__file__)  
      244          
    241 245         # positive matches  
    242 246         assert plug.match(foo, ':FooTest.test_bar')  
    243 247         assert plug.match(foo, ':FooTest')  
    244           assert plug.match(foo, __file__)  
    245           assert plug.match(foo, os.path.dirname(__file__))  
      248         assert plug.match(foo, here)  
      249         assert plug.match(foo, os.path.dirname(here))  
    246 250         assert plug.match(foo, __name__)  
    247 251         assert plug.match(baz, ':test_baz')  
    248           assert plug.match(baz, __file__)  
      252         assert plug.match(baz, here)  
    248 252         assert plug.match(baz, __name__)  
    249 253         assert plug.match(quz, ':QuzTest.test_whatever')  
    250 254         assert plug.match(quz, ':QuzTest')  
    251           assert plug.match(quz, __file__)  
      255         assert plug.match(quz, here)  
    251 255         assert plug.match(quz, __name__)  
    252 256          
  • trunk/unit_tests/test_collector.py

    r21 r23  
    45 45  
    46 46         expect = [ 'test module foo in %s' % c.where,  
      47                    'test directory %s/foo in foo' % c.where,  
    47 48                    'test module foo.bar in %s' % c.where,  
    48 49                    'test module foo.test_foo in %s' % c.where,  
  • trunk/nose/core.py

    r21 r23  
    169 169     verbosity = 1  
    170 170  
    171       # FIXME is this the same signature as unittest?  
    172       # FIXME no it is not. fix this!  
    173       def __init__(self, argv=None, env=None, testRunner=None,  
    174                    testCollector=defaultTestCollector, stream=sys.stderr):  
      171     def __init__(self, module=None, defaultTest=defaultTestCollector,  
      172                  argv=None, testRunner=None, testLoader=None, env=None,  
      173                  stream=sys.stderr):  
    175 174         self.testRunner = testRunner  
    176           self.testCollector = testCollector  
      175         self.testCollector = defaultTest  
      176         self.testLoader = testLoader  
    177 177         self.stream = stream  
    178 178         self.success = False  
    179           self.tests = None  
      179         self.module = module  
      180  
      181         if not callable(self.testCollector):  
      182             raise ValueError("TestProgram argument defaultTest must be "  
      183                              "a callable with the same signature as "  
      184                              "TestCollector()")  
    180 185          
    181 186         if argv is None:  
     
    191 196         """  
    192 197         self.conf = configure(argv, env)  
    193    
      198         # append the requested module to the list of tests to run  
      199         if self.module:  
      200             try:  
      201                 self.conf.tests.append(self.module.__name__)  
      202             except AttributeError:  
      203                 self.conf.tests.append(str(self.module))  
      204                  
    194 205     def createTests(self):  
    195           """Discover tests using TestCollector  
      206         """Create the tests to run. Default behavior is to discover  
      207         tests using TestCollector using nose.loader.TestLoader as the  
      208         test loader.  
    196 209         """  
    197           self.test = self.testCollector(self.conf)  
      210         self.test = self.testCollector(self.conf, self.testLoader)  
    197 210  
    198 211     def runTests(self):  
     
    266 279                       default=env.get('NOSE_PDB_FAILURES'),  
    267 280                       help="Drop into debugger on failures")  
      281     parser.add_option("--stop", action="store_true", dest="stopOnError",  
      282                       default=env.get('NOSE_STOP'),  
      283                       help="Stop running tests after the first error or "  
      284                       "failure")  
    268 285     parser.add_option("-P", "--no-path-adjustment", action="store_false",  
    269 286                       dest="addPaths",  
     
    287 304      
    288 305     try:  
    289           conf.tests = args[1:]  
      306         log.debug('Adding %s to tests to run' % args[1:])  
      307         conf.tests.extend(args[1:])  
    290 308     except IndexError:  
    291           conf.tests = None  
      309         pass  
    291 309      
    292 310     if options.version:  
     
    311 329     conf.debugFailures = options.debugFailures  
    312 330     conf.plugins = [ plug for plug in all_plugins if plug.enabled ]  
      331     conf.stopOnError = options.stopOnError  
    313 332     conf.verbosity = options.verbosity  
    314 333      
  • trunk/nose/suite.py

    r21 r23  
    106 106             yield test  
    107 107  
      108  
      109 class TestDir(LazySuite):  
      110     """Test collector that collects tests from a directory.  
      111     """  
      112     def __init__(self, loadtests, conf, path, module=None, importPath=None):  
      113         self.path = path  
      114         self.module = module  
      115         self.importPath = importPath  
      116         super(TestDir, self).__init__(loadtests, conf)  
      117  
      118     def __repr__(self):  
      119         return "test directory %s in %s" % (self.path, self.module)  
      120     __str__ = __repr__  
      121          
      122     def loadtests(self):  
      123         for test in self._loadtests(self.path, self.module,  
      124                                     self.importPath):  
      125             yield test  
      126  
    108 127              
    109 128 class TestModule(LazySuite):  
     
    125 144     fromDirectory = None  
    126 145      
    127       def __init__(self, loadtests, conf, moduleName, path):  
      146     def __init__(self, loadtests, conf, moduleName=None, path=None,  
      147                  module=None):  
    128 148         self.moduleName = moduleName  
    129 149         self.path = path  
    130           self.module = None  
    131           super(TestModule, self).__init__(loadtests, conf)         
      150         self.module = module  
      151         if module and moduleName is None:  
      152             self.moduleName = module.__name__         
      153         super(TestModule, self).__init__(loadtests, conf)  
    132 154          
    133 155     def __repr__(self):  
     
    150 172         the test package or module will be passed to the setup function.  
    151 173         """  
    152           self.module = _import(self.moduleName, [self.path], self.conf)  
      174         if self.module is None:  
      175             self.module = _import(self.moduleName, [self.path], self.conf)  
    153 176  
    154 177         if hasattr(self.module, '__path__'):  
  • trunk/nose/plugins/base.py

    r21 r23  
    75 75         # might be a string  
    76 76         try:  
    77               return re.split(r'\W+', val)  
      77             return re.split(r'\s*,\s*', val)  
    77 77         except TypeError:  
    78 78             # who knows...  
  • trunk/nose/plugins/cover.py

    r22 r23  
    84 84                     for name, module in sys.modules.items()  
    85 85                     if self.wantModuleCoverage(name, module) ]  
      86         log.debug("Coverage report will cover modules: %s", modules)  
    86 87         coverage.report(modules, stream)  
    87 88  
  • trunk/nose/plugins/profile.py

    r20 r23  
    11 11 import logging  
    12 12 import os  
      13 import sys  
    13 14 from nose.plugins.base import Plugin  
    14 15  
     
    33 34                           default=env.get('NOSE_PROFILE_RESTRICT'),  
    34 35                           help="Restrict profiler output. See help for "  
    35                             "pstats.stats for details")  
      36                           "pstats.Stats for details")  
    35 36      
    36 37     def begin(self):  
     
    62 63         stats = hotshot.stats.load(self.pfile)  
    63 64         stats.sort_stats(self.sort)  
    64           # FIXME capt. stdout, redirect to stream  
    65           stats.print_stats(*self.restrict)  
      65         try:  
      66             tmp = sys.stdout  
      67             sys.stdout = stream  
      68             if self.restrict:  
      69                 log.debug('setting profiler restriction to %s', self.restrict)  
      70                 stats.print_stats(*self.restrict)  
      71             else:  
      72                 stats.print_stats()  
      73         finally:  
      74             sys.stdout = tmp  
  • trunk/nose/plugins/missed.py

    r20 r23  
    23 23         adr_file, adr_mod, adr_tst = test_address(test)  
    24 24         chk_file, chk_mod, chk_tst = split_test_name(test_name)  
    25    
      25          
    25 25         if chk_file is not None and not adr_file.startswith(chk_file):  
    26 26             return False  
  • trunk/nose/util.py

    r21 r23  
    92 92     t = type(test)  
    93 93     if t == types.ModuleType:  
    94           return (test.__file__, test.__name__)  
      94         return (os.path.abspath(test.__file__), test.__name__)  
    94 94     if t == types.FunctionType:  
    95 95         m = sys.modules[test.__module__]  
    96           return (m.__file__, test.__module__, test.__name__)  
      96         return (os.path.abspath(m.__file__), test.__module__, test.__name__)  
    96 96     if t in (type, types.ClassType):  
    97 97         m = sys.modules[test.__module__]  
    98           return (m.__file__, test.__module__, test.__name__)  
      98         return (os.path.abspath(m.__file__), test.__module__, test.__name__)  
    98 98     if t == types.InstanceType:  
    99 99         return test_address(test.__class__)  
  • trunk/nose/result.py

    r21 r23  
    1 1 import inspect  
      2 import logging  
    2 3 import pdb  
    3 4 import sys  
     
    16 17 stdout = []  
    17 18  
      19 log = logging.getLogger('nose.result')  
    18 20  
    19 21 class Result(object):  
     
    44 46             call_plugins(self.conf.plugins, 'addError',  
    45 47                          test, err, self.capt)  
      48         if self.conf.stopOnError:  
      49             self.shouldStop = True  
    46 50              
    47 51     def addFailure(self, test, err):  
     
    63 67         call_plugins(self.conf.plugins, 'addFailure',  
    64 68                      test, err, self.capt, self.tbinfo)  
      69         if self.conf.stopOnError:  
      70             self.shouldStop = True  
    65 71          
    66 72     def addSkip(self, test):  
     
    163 169          
    164 170     def printErrors(self):  
      171         log.debug('printErrors called')  
    165 172         super(TextTestResult, self).printErrors()  
    166 173         self.printErrorList('DEPRECATED', self.deprecated)  
    167 174         self.printErrorList('SKIPPED', self.skip)  
      175         log.debug('calling plugin reports')  
    168 176         call_plugins(self.conf.plugins, 'report', self.stream)  
    169 177          
  • trunk/nose/selector.py

    r21 r23  
    34 34         matches = [ func(*test_tuple) for test_tuple in  
    35 35                     map(split_test_name, self.tests) ]  
    36           return filter(lambda x: x is not False, matches)  
      36         log.debug('anytest matches: %s', matches)  
      37         res = filter(lambda x: x is not False, matches)  
      38         log.debug('anytest result: %s', res)  
      39         return res  
    37 40  
    38 41     def callableInTests(self, clb, matches):  
     
    50 53             containerMatch = False  
    51 54             if filename is not None:  
      55                 orig = filename  
      56                 # always compare with the *source* file  
      57                 if (filename.endswith('.pyc')                     
      58                     or filename.endswith('.pyo')):  
      59                     filename = filename[:-3] + 'py'  
    52 60                 if not os.path.isabs(filename):  
    53                       filename = absfile(filename)  
      61                     filename = absfile(filename, self.conf.where)  
      62                     if filename is None:  
      63                         log.warning("File %s not found",  orig)  
      64                         return False  
    54 65                 log.debug("Check file match for callable %s in module %s",  
    55 66                           clb, clb.__module__)  
    56 67                 try:  
    57 68                     mod_file = sys.modules[clb.__module__].__file__  
      69                     # always compare against the *source* file  
      70                     if (mod_file.endswith('.pyc')  
      71                         or mod_file.endswith('.pyo')):  
      72                         mod_file = mod_file[:-3] + 'py'  
      73                     log.debug("module file: %s", mod_file)  
    58 74                     if not os.path.isabs(mod_file):  
    59 75                         mod_file = absfile(mod_file, self.conf.where)  
      76                     log.debug("%s == %s?", mod_file, filename)  
    60 77                     if mod_file == filename:  
      78                         log.debug("File matches")  
    61 79                         containerMatch = True  
    62 80                 except AttributeError:  
    63                       # we tried to look at something in __builtin__  
      81                     # we tried to look at something in __builtin__,  
      82                     # for instance  
    64 83                     return False  
    65 84             if modname is not None and not containerMatch:  
     
    101 120         if not os.path.isabs(file):  
    102 121             file = absfile(file, self.conf.where)  
      122             log.debug("abs file %s is %s", orig, file)  
    103 123         if file is None:  
    104 124             log.debug("File %s does not exist" % orig)  
  • trunk/nose/config.py

    r14 r23  
      1 import copy  
    1 2 import os  
    2 3 import re  
     
    5 6     """nose configuration. For internal use only.  
    6 7     """  
    7       default = dict(  
    8           testMatch=re.compile(r'(?:^|[\b_\.%s-])[Tt]est' % os.sep),  
    9           addPaths=True,  
    10           capture=True,  
    11           detailedErrors=False,  
    12           debugErrors=False,  
    13           debugFailures=False,  
    14           exclude=None,  
    15           ignore=[],  
    16           include=None,  
    17           plugins=[],  
    18           srcDirs=['lib', 'src'],  
    19           tests=None,  
    20           verbosity=1,  
    21           where=None  
    22           )  
    23 8  
    24 9     def __init__(self, **kw):  
    25           self.update(Config.default)  
      10         self.testMatch=re.compile(r'(?:^|[\b_\.%s-])[Tt]est' % os.sep)  
      11         self.addPaths=True  
      12         self.capture=True  
      13         self.detailedErrors=False  
      14         self.debugErrors=False  
      15         self.debugFailures=False  
      16         self.exclude=None  
      17         self.ignore=[]  
      18         self.include=None  
      19         self.plugins=[]  
      20         self.srcDirs=['lib', 'src']  
      21         self.stopOnError=False  
      22         self.tests=[]  
      23         self.verbosity=1  
      24         self.where=None  
    26 25         self.update(kw)  
    27        
      26         self._orig = copy.deepcopy(self.__dict__)  
      27          
    28 28     def __str__(self):  
    29 29         # FIXME -- in alpha order  
     
    31 31  
    32 32     def reset(self):  
    33           self.__dict__.update(Config.default)  
      33         self.__dict__.update(self._orig)  
    33 33  
    34 34     def todict(self):  
  • trunk/nose/loader.py

    r21 r23  
    9 9 from nose.plugins import call_plugins  
    10 10 from nose.selector import defaultSelector  
    11   from nose.suite import LazySuite, TestClass, TestModule, \  
      11 from nose.suite import LazySuite, TestClass, TestDir, TestModule, \  
    11 11     GeneratorMethodTestSuite  
    12 12 from nose.util import is_generator, split_test_name, try_run  
     
    85 85             # setting the module prefix means that we're  
    86 86             # loading from our own parent directory, since we're  
    87               # loading xxx.yyy, not just yyy, so ask the importer  
    88               # to load from self.path (the path we loaded from),  
      87             # loading xxx.yyy, not just yyy, so ask the importer to  
      88             # import from self.path (the path we were imported from),  
    89 89             # not path (the path we're at now)  
    90               for test in self.loadTestsFromDir(path,  
    91                                                 module=module.__name__,  
    92                                                 importPath=importPath):  
    93                   tests.append(test)  
      90             tests.append(TestDir(self.loadTestsFromDir, self.conf, path,  
      91                                  module.__name__, importPath))  
    94 92         # compat w/unittest  
    95 93         return self.suiteClass(tests)  
     
    165 163                     yield test  
    166 164  
    167       # FIXME if names is a string, parse it as cmd line args  
    168 165     def loadTestsFromNames(self, names, module=None):  
    169           # compatiblity shim ...  
    170           try:  
    171               module = module.__name__  
    172           except AttributeError:  
    173               pass  
    174           if names:  
    175               self.conf.tests = names  
      166         """Load tests from names. Behavior is compatible with unittest:  
      167         if module is specified, all names are translated to be relative  
      168         to that module; the tests are appended to conf.tests, and  
      169         loadTestsFromModule() is called. Otherwise, the names are  
      170         loaded one by one using loadTestsFromName.  
      171         """  
      172                      
      173         def rel(name, mod):  
      174             if not name.startswith(':'):  
      175                 name = ':' + name  
      176             return "%s%s" % (mod, name)  
      177          
      178         if module:  
      179             log.debug("load tests from module %r" % module)  
      180             # configure system to load only requested tests from module  
      181             if names:  
      182                 self.conf.tests.extend([ rel(n, module.__name__)  
      183                                          for n in names ])  
      184  
      185             try:  
      186                 mpath = os.path.dirname(module.__path__[0])  
      187             except AttributeError:  
      188                 mpath = os.path.dirname(module.__file__)  
      189                  
      190             #return self.loadTestsFromModule(module)  
      191             return TestModule(self.loadTestsFromModule,  
      192                               self.conf,  
      193                               module=module,  
      194                               path=mpath)  
    176 195         else:  
    177               names = [ module ]  
    178               module = None  
    179           tests = []  
    180           for name in names:  
    181               tests.extend([ test  
    182                              for test in self.loadTestsFromName(name,  
    183                                                                 module) ])  
      196             tests = []  
      197             for name in names:  
      198                 for test in self.loadTestsFromName(name):  
      199                     tests.append(test)         
    184 200         return self.suiteClass(tests)  
    185 201