Changeset 20

Show
Ignore:
Timestamp:
Thu Apr 6 21:57:13 2006
Author:
jpellerin
Message:

Documentation updates; closes #10 and #25

Files:

Legend:

Unmodified
Added
Removed
Modified
  • trunk/nose/core.py

    r18 r20  
    1   """Implements core nose test discovery functions.  
      1 """Implements nose test program and collector.  
    1 1 """  
    2 2 import logging  
     
    15 15 from nose.loader import defaultTestLoader  
    16 16 from nose.selector import defaultSelector  
    17   from nose.suite import LazySuite  
      17 from nose.suite import LazySuite, ResultProxySuite  
    17 17 from nose.util import absdir, absfile, try_run  
    18 18  
     
    22 22  
    23 23 class TestCollector(LazySuite):  
    24       """Discovery-based test suite. FIXME docs out of date  
      24     """Main nose test collector.  
    24 24  
    25       Unless told not to, the collector looks in the current directory for  
    26       test packages, modules, or directories and creates test suites to run  
    27       all tests in any found. A list of tests to run may also be specified.  
    28    
    29       Test modules, packages or directories are:  
    30         * Any directory with 'test' in the name (will be loaded as a test  
    31           package if it contains an __init__.py file, otherwise as a test  
    32           directory)  
    33         * And file with 'test' in the name (will be loaded as a test module)  
      25     Uses a test loader to load tests from the directory given in conf  
      26     (conf.path). Uses the default test loader from nose.loader by  
      27     default. Any other loader may be used so long as it implements  
      28     loadTestsFromDir().     
    34 29     """  
    35 30      
     
    55 50 def collector():  
    56 51     """TestSuite replacement entry point. Use anywhere you might use a  
    57       unittest.TestSuite. Note: Except with testoob; currently (nose 0.8)  
      52     unittest.TestSuite. Note: Except with testoob; currently (nose 0.9)  
    57 52     testoob's test loading is not compatible with nose's collector  
    58 53     implementation.  
      54  
      55     Returns a TestCollector configured to use a TestLoader that returns  
      56     ResultProxySuite test suites, which use a proxy result object to  
      57     enable output capture and assert introspection.  
    59 58     """  
      59     # FIXME somehow restrict plugin methods  
    60 60     conf = configure(env=os.environ)  
    61       result.install_patch(conf)  
    62    
    63       # FIXME if any plugin implements prepareTest, here must patch  
    64       # unittest.TextTestRunner.run with run like nose's TextTestRunner  
    65       return TestCollector(conf)  
      61     loader = defaultTestLoader(conf)  
      62     loader.suiteClass = ResultProxySuite  
      63     return TestCollector(conf, loader)  
    66 64  
    67 65              
    68 66 class TextTestRunner(unittest.TextTestRunner):  
    69    
      67     """Test runner that uses nose's TextTestResult to enable output  
      68     capture and assert introspection, as well as providing hooks for  
      69     plugins to override or replace the test output stream, results, and  
      70     the test case itself.  
      71     """     
    70 72     def __init__(self, stream=sys.stderr, descriptions=1, verbosity=1,  
    71 73                  conf=None):  
     
    106 108     directories and packages found in its working directory (which  
    107 109     defaults to the current working directory). Any python source file,  
    108       directory or package that matches nose.core.testMatch (by default:  
    109       (?:^|[\b_\.-])[Tt]est) will be collected as a test (or source for  
    110       collection of tests). In addition, all other packages found in the  
    111       working directory are examined for python source files or directories  
    112       that match nose.core.testMatch. Package discovery descends all the way  
    113       down the tree, so package.tests and package.sub.tests and  
      110     directory or package that matches the testMatch regulat expression  
      111     (by default: (?:^|[\b_\.-])[Tt]est) will be collected as a test (or  
      112     source for collection of tests). In addition, all other packages  
      113     found in the working directory are examined for python source files  
      114     or directories that match testMatch. Package discovery descends all  
      115     the way down the tree, so package.tests and package.sub.tests and  
    114 116     package.sub.sub2.tests will all be collected.  
    115 117      
    116 118     Within a test directory or package, any python source file matching  
    117       nose.core.testMatch will be examined for test cases. Within a test  
    118       file, functions with 'test' in the name and TestCase subclasses (with  
    119       any name) will be loaded and executed as tests. Functional tests may  
    120       use the assert keyword or raise AssertionErrors to indicate test  
    121       failure; TestCase subclasses may do the same or use the various  
      119     testMatch will be examined for test cases. Within a test file,  
      120     functions and classes whose names match testMatch and TestCase  
      121     subclasses with any name will be loaded and executed as tests. Tests  
      122     may use the assert keyword or raise AssertionErrors to indicate test  
      123     failure. TestCase subclasses may do the same or use the various  
    122 124     TestCase methods available.  
    123        
    124       Some options may also be set by env variables. For those options, the  
    125       env variable appears in brackets at the end of the option  
    126       description. Command line settings will override environment settings.  
    127        
      125  
      126     Tests may raise nose.SkipTest to indicate that they should be  
      127     skipped or nose.DeprecatedTest to indicate that they are  
      128     deprecated. Skipped and deprecated tests do not count as failures,  
      129     but details on them are printed at the end of the test run along  
      130     with any failures and erorrs.  
      131          
    128 132     Selecting Tests  
    129 133     ---------------  
    130 134  
    131       To specify additional tests to run, beyond those found in discovery, pass  
    132       test names on the command line::  
      135     To specify which tests to run, pass test names on the command line::  
    133 136  
    134         %prog also_this.py  
      137       %prog only_test_this.py  
    134 137  
    135       (FIXME -- update test selection notes to new selector/test address syntax)  
      138     Test names specified may be file or module names, and may optionally  
      139     indicate the test case to run by separating the module or file name  
      140     from the test case name with a colon. Examples::  
      141  
      142       %prog test.module  
      143       %prog another.test:TestCase.test_method  
      144       %prog a.test:TestCase  
      145       %prog /path/to/test/file.py:test_function  
      146        
      147     Note however that specifying a test name will *not* cause nose to run  
      148     a test that it does not discover. Test names specified are compared  
      149     against tests discovered, and only the requested tests are  
      150     run. Setup and teardown methods are run at all stages. That means  
      151     that if you run::  
      152  
      153       %prog some.tests.test_module:test_function  
      154  
      155     And have defined setup or teardown methods in tests and test_module,  
      156     those setup methods will run before the test_function test, and  
      157     teardown after, just as if you were running all tests.  
    136 158  
    137 159     You may also change the working directory where nose looks for tests,  
     
    140 162  
    141 163       %prog -w /path/to/tests  
      164  
      165     Further customization of test selection and loading is possible  
      166     through the use of plugins.  
    142 167     """  
    143 168     verbosity = 1  
     
    246 271                       help="Don't make any changes to sys.path when "  
    247 272                       "loading tests [NOSE_NOPATH]")  
    248    
    249 273      
    250 274     # add opts from plugins  
     
    350 374              
    351 375 def main(*arg, **kw):  
    352       """Collect and run test, returning success or failure  
      376     """Run and exit with 0 on success or 1 on failure.  
    352 376     """  
    353       return TestProgram(*arg, **kw).success  
      377     return sys.exit(not run(*arg, **kw))  
    353 377  
      378 # backwards compatibility  
      379 run_exit = main  
    354 380  
    355   def run_exit(*arg, **kw):  
    356       """Run main() and exit with 0 on success or 1 on failure.  
      381 def run(*arg, **kw):  
      382     """Collect and run test, returning success or failure  
    357 383     """  
    358       sys.exit(not main(*arg, **kw))  
      384     return TestProgram(*arg, **kw).success  
    358 384      
    359 385          
    360   # FIXME move to util  
      386 # FIXME move to tools?  
    360 386 def with_setup(setup=None, teardown=None):  
    361 387     """Decorator to add setup and/or teardown methods to a test function  
  • trunk/nose/suite.py

    r18 r20  
    61 61         pass  
    62 62  
      63  
      64 class ResultProxySuite(LazySuite):  
      65     pass  
      66      
    63 67      
    64 68 class TestClass(LazySuite):  
  • trunk/nose/plugins/doctests.py

    r15 r20  
    24 24  
    25 25 class Doctest(Plugin):  
    26       """Activate doctest plugin to find and run doctest in non-test modules.  
      26     """  
      27     Activate doctest plugin to find and run doctest in non-test modules.  
    27 28     """  
    28 29     extension = None  
  • trunk/nose/plugins/base.py

    r18 r20  
    80 80             return list(val)  
    81 81  
      82          
    82 83 class PluginInterface(object):  
    83 84     """  
     
    98 99     and returns a non-None value wins, and plugin processing ends. The  
    99 100     only exceptions to are `loadTestsFromModule`, `loadTestsFromName`,  
    100       and `loadTestsFromPath`, which allow multiple plugins to load tests.  
      101     and `loadTestsFromPath`, which allow multiple plugins to load and  
      102     return tests.  
    101 103  
    102 104     In general, plugin methods correspond directly to the methods of  
    103 105     nose.selector.Selector, nose.loader.TestLoader and  
    104       nose.result.TextTestResult where they are called. In some cases, the  
    105       plugin hook doesn't neatly match the method in which it is called;  
    106       for those, the documentation for the hook will tell you where in the  
    107       test process it is available.  
      106     nose.result.TextTestResult are called by those methods when they are  
      107     called. In some cases, the plugin hook doesn't neatly match the  
      108     method in which it is called; for those, the documentation for the  
      109     hook will tell you where in the test process it is called.  
    108 110  
    109 111     Plugin hooks fall into two broad categories: selecting and loading  
  • trunk/nose/plugins/__init__.py

    r18 r20  
    40 40 that want the standard options should call the superclass methods.  
    41 41  
    42   defining command-line and environment options  
      42 nose uses optparse.OptionParser from the standard library to parse  
      43 arguments. A plugin's add_options() method receives a parser  
      44 instance. It's good form for a plugin to use that instance only to add  
      45 additional arguments that take only long arguments (--like-this). Most  
      46 of nose's built-in arguments get their default value from an environment  
      47 variable. This is a good practice because it allows options to be  
      48 utilized when run through some other means than the nosetests script.  
      49  
      50 A plugin's configure() receives the parsed OptionParser options object,  
      51 as well as the current config object. Plugins should configure their  
      52 behavior based on the user-selected settings, and may raise exceptions  
      53 if the configured behavior is nonsensical.  
    43 54  
    44   configuring from selected options  
      55 Logging  
      56 =======  
    45 57  
    46   logging  
      58 nose uses the logging classes from the standard library. To enable users  
      59 to view debug messages easily, plugins should use logging.getLogger() to  
      60 acquire a logger in the 'nose.plugins' namespace.  
    47 61  
    48 62 Recipes  
     
    90 104  
    91 105 See nose.plugins.attrib, nose.plugins.cover, nose.plugins.doctests and  
    92   nose.plugins.profile for examples.  
    93    
    94   examples in examples/ dir...  
      106 nose.plugins.profile for examples. Further examples may be found the  
      107 examples directory in the nose source distribution.  
    95 108 """  
    96 109 import logging  
  • trunk/nose/plugins/profile.py

    r17 r20  
    1   """FIXME module docs  
      1 """Use the profile plugin with --with-profile or NOSE_WITH_PROFILE to  
      2 enable profiling using the hotshot profiler. Profiler output can be  
      3 controlled with the --profile-sort and --profile-restrict, and the  
      4 profiler output file may be changed with --profile-stats-file.  
    2 5  
    3   FIXME change module name to profiler to avoid conflict w/builtin profile.py  
      6 See the hotshot documentation in the standard library documentation for  
      7 more details on the various output options.  
    4 8 """  
    5 9  
     
    12 16  
    13 17 class Profile(Plugin):  
    14       """FIXME usage help  
      18     """  
      19     Use this plugin to run tests using the hotshot profiler.  
    15 20     """  
    16 21     def add_options(self, parser, env=os.environ):  
     
    42 47         else:  
    43 48             # FIXME use a temp file  
    44               self.pfile = 'FIXME'  
      49             self.pfile = 'nose.profile'  
    44 49         self.sort = options.profile_sort  
    45 50         self.restrict = self.tolist(options.profile_restrict)  
  • trunk/nose/plugins/missed.py

    r18 r20  
    3 3  
    4 4 class MissedTests(Plugin):  
    5       """Enable to get a warning when tests specified on the command line  
      5     """  
      6     Enable to get a warning when tests specified on the command line  
    6 7     are not found during the test run.  
    7 8     """  
     
    18 19             for missed in self.missed:  
    19 20                 result.stream.writeln("WARNING: missed test '%s'" % missed)  
    20    
    21       def startTest(self, test):  
    22           if not self.missed:  
    23               return  
    24           found = []  
    25           for name in self.missed:  
    26               if self.match(test, name):  
    27                   found.append(name)  
    28           for name in found:  
    29               self.missed.remove(name)  
    30 21          
    31 22     def match(self, test, test_name):  
     
    49 40                 return False  
    50 41         return True  
      42  
      43     def startTest(self, test):  
      44         if not self.missed:  
      45             return  
      46         found = []  
      47         for name in self.missed:  
      48             if self.match(test, name):  
      49                 found.append(name)  
      50         for name in found:  
      51             self.missed.remove(name)  
  • trunk/nose/__init__.py

    r14 r20  
    17 17   nose.main()  
    18 18  
    19   If you want the test script to exit with 0 on success and 1 on failure  
    20   (like unittest.main), use nose.run_exit() instead::  
      19 If you don't want the test script to exit with 0 on success and 1 on failure  
      20 (like unittest.main), use nose.run() instead::  
    21 21  
    22 22   import nose  
    23     nose.run_exit()  
      23   nose.run()  
    23 23    
    24   Lastly, you can nose.core directly::  
      24 Lastly, you can run nose.core directly, which will run nose.main()::  
    24 24  
    25 25   python /path/to/nose/core.py  
    26 26  
    27 27 Please see the usage message for the nosetests script for information  
    28   about how to control which tests nose runs and the test output.  
      28 about how to control which tests nose runs, which plugins are loaded,  
      29 and the test output.  
    29 30    
    30 31 Features  
     
    49 50 because teardown has not yet run at the time of the failure.)  
    50 51  
    51   When running as a setup command, output capture is implemented by  
    52   patching nose's test result class into unittest.  
    53    
    54 52 Assert introspection  
    55 53 ====================  
     
    67 65       assert a == 4, "assert 2 is 4"  
    68 66  
    69   You will get output something like::  
      67 You will get output like::  
    69 67  
    70 68   File "/path/to/file.py", line XX, in test_integers:  
     
    73 71   InspectAssertionError: assert 2 is 4  
    74 72     >>  assert 2 == 4, "assert 2 is 4"  
    75    
    76   When running as a setuptools command, assert introspection is  
    77   implemented by patching nose's test result class into unittest.  
    78 73      
    79 74 Setuptools integration  
     
    94 89 When running under setuptools, you can configure nose settings via the  
    95 90 environment variables detailed in the nosetests script usage message.  
    96        
      91  
      92 Please note that when run under setuptools, some plugins will not be  
      93 available, including the builtin coverage, profiler, and missed test  
      94 plugins.  
      95  
      96 nose 1.0 will include a custom setuptools command that will enable all  
      97 plugins available when running nosetests.  
      98  
    97 99 .. _setuptools: http://peak.telecommunity.com/DevCenter/setuptools  
    98 100  
     
    200 202 ===============  
    201 203  
    202   nose supports test functions that are generators. A simple example from nose's  
    203   selftest suite is probably the best explanation::  
      204 nose supports test functions and methods that are generators. A simple  
      205 example from nose's selftest suite is probably the best explanation::  
    204 206  
    205 207   def test_evens():  
     
    244 246 --------------------  
    245 247  
    246   nose was inspired mainly by py.test_, which is far more functional than  
    247   nose, but is not all that easy to install, and is not based on unittest.  
      248 nose was inspired mainly by py.test_, which is a great test runner, but  
      249 formerly was not all that easy to install, and is not based on unittest.  
    248 250  
    249 251 TestGears_ is a similar test runner (now part of TurboGears) that was  
     
    277 279 along with this program; if not, write to the Free Software Foundation,  
    278 280 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA  
    279    
    280   TODO  
    281    
    282   * Docstrings for all classes  
    283   * Output better shortDescription()s  
    284 281 """  
    285 282