PageRenderTime 25ms CodeModel.GetById 2ms app.highlight 20ms RepoModel.GetById 1ms app.codeStats 0ms

/NOTES

https://bitbucket.org/jpellerin/nose/
#! | 151 lines | 112 code | 39 blank | 0 comment | 0 complexity | 44eb4341d7602b7929a7de75c01fd8ce MD5 | raw file
  1-- 2/3/07
  2
  3is the selector useful? can it die, if we assume a more directed loading
  4approach?
  5
  6The loader is the heart of the discovery system. It should be simple, clear,
  7and close to unittest's loader whereever possible. The complication comes from
  8supporting proper fixture setup and teardown when the test name requested is a
  9or is inside of a dotted module. Say we run like this:
 10
 11nosetests foo/bar/baz.py
 12
 13that should look in foo for setup, then baz for setup, but only after
 14importing the target module (baz) and finding any tests therein. If baz has
 15tests, then foo.setup runs, bar.setup runs, baz.setup runs, baz's tests run,
 16then baz.teardown, bar.teardown, foo.teardown.
 17
 18nosetests w/o argument is identical in meaning to nosetests .
 19-> loader.loadTestsFromNames(names=[.])
 20
 21nosetests foo and nosetests -w foo are identical in meaning
 22-> loader.loadTestsFromNames(names=['foo'])
 23
 24loadTestsFromName(name, module=None):
 25    if module is None:
 26        module, name = importable module parts of name, the rest
 27        or, name is a dir
 28    if module:
 29        find name within the module
 30        find all tests in that object (could be the module itself)
 31        return a suite
 32    elif dir:
 33        find all the names in the dir that look like test modules
 34        recurse into load tests from names with that name list
 35
 36loadTestsFromNames(names, module=None):
 37    for name in names:
 38        yield self.suiteClass(self.loadTestsFromName(name, module))
 39
 40responsibility for proper setup/teardown lies in the runner, or the suite
 41class?
 42
 43how do they know the running context?
 44
 45the loader returns tests wrapped in a Context() closure
 46the Context() keeps track of what fixtures have been run and what fixtures
 47need to be run at setup and teardown
 48
 49setup is easy -- the first test triggers a cascade of setup calls up to the
 50package level
 51
 52but how can we know when to run teardowns? the last test in a module, the last
 53test in a package should trigger the teardowns at that level... it's not clear
 54how to know what test is the last?
 55
 56we know what's last because tests for a given package don't start running
 57until they have all been collected.
 58
 59
 60the process of 
 61        
 62-- old
 63notes on loading from modules
 64
 65this pretty much all has to take place inside of the _tests iterator.
 66
 67
 68if the module is wanted
 69   run setup
 70   load tests (including submodules) and yield each test
 71   run teardown
 72else if the module is not wanted:
 73   * do not import the module *
 74   if the module is a package:
 75      recurse into the package looking for test modules
 76
 77
 78make suite.TestSuite
 79put run, call, setup, teardown, shortdescription there
 80
 81make LazySuite subclass it
 82
 83get rid of TestModule
 84
 85do module import in loadTestsFromModuleName; if an error, pass the error
 86to the module suite, whose run() should re-raise the error so that import
 87errors are seen only when we actually try to run the tests
 88
 89make ModuleSuite class with setUp, tearDown doing try_run, it gets
 90additional module and error keyword args
 91
 92rename TestDir to DirectorySuite
 93
 94try to make things less stateful
 95
 96 - conf should be immutable?
 97 - certainly conf.working_dir shouldn't change, or if it does it has to be a
 98   stack
 99 - things that are mutable should be removed from conf and passed separately
100
101tests and working dir should come out of conf and be passed to loader and
102selector
103
104loader.loadTestsFromNames(names, module=None, working_dir=None)
105 -> split and absolutize all of the test names
106 -> give them to the selector (self.selector.tests = names)
107 -> start walking at working_dir
108 -> sort dirnames into test-last order
109 -> yield loadFromName for wanted files
110    -> ModuleSuite
111 -> for directories:
112    - keep descending if wanted and not a package
113    - remove from list if not wanted
114    - if a package, yield loadFromName for package
115      -> ModuleSuite
116      -> since module has a path, we need to restart the walk
117         and call loadTestsFromNames with the path end as the working dir
118         but we want to do that lazily, so we need to bundle up the
119         needed information into a callable and a LazySuite
120
121loader.collectTests(working_dir, names=[]):
122 -> yield each test suite as found
123
124
125suites:
126
127ModuleSuite
128ClassSuite
129TestCaseSuite
130GeneratorSuite
131GeneratorMethodSuite
132
133
134*
135proxy suite may need to be mixed in by the collector when running under test
136or, suite base class has a testProxy property, which if not None is called to
137proxy the test
138
139*
140module isolation plugin will break under depth-first loading. how to restore
141it:
142
143preImport hook
144 - snapshot sys.modules: this is what to restore AFTER processing of the
145   test module is complete
146postImport hook
147 - snapshot sys.modules: this is what to restore BEFORE running module tests
148startTest
149 - if isa module, restore postImport sys.modules snapshot
150stopTest
151 - if isa module, restore preImport sys.modules snapshot