-- 2/3/07 is the selector useful? can it die, if we assume a more directed loading approach? The loader is the heart of the discovery system. It should be simple, clear, and close to unittest's loader whereever possible. The complication comes from supporting proper fixture setup and teardown when the test name requested is a or is inside of a dotted module. Say we run like this: nosetests foo/bar/baz.py that should look in foo for setup, then baz for setup, but only after importing the target module (baz) and finding any tests therein. If baz has tests, then foo.setup runs, bar.setup runs, baz.setup runs, baz's tests run, then baz.teardown, bar.teardown, foo.teardown. nosetests w/o argument is identical in meaning to nosetests . -> loader.loadTestsFromNames(names=[.]) nosetests foo and nosetests -w foo are identical in meaning -> loader.loadTestsFromNames(names=['foo']) loadTestsFromName(name, module=None): if module is None: module, name = importable module parts of name, the rest or, name is a dir if module: find name within the module find all tests in that object (could be the module itself) return a suite elif dir: find all the names in the dir that look like test modules recurse into load tests from names with that name list loadTestsFromNames(names, module=None): for name in names: yield self.suiteClass(self.loadTestsFromName(name, module)) responsibility for proper setup/teardown lies in the runner, or the suite class? how do they know the running context? the loader returns tests wrapped in a Context() closure the Context() keeps track of what fixtures have been run and what fixtures need to be run at setup and teardown setup is easy -- the first test triggers a cascade of setup calls up to the package level but how can we know when to run teardowns? the last test in a module, the last test in a package should trigger the teardowns at that level... it's not clear how to know what test is the last? we know what's last because tests for a given package don't start running until they have all been collected. the process of -- old notes on loading from modules this pretty much all has to take place inside of the _tests iterator. if the module is wanted run setup load tests (including submodules) and yield each test run teardown else if the module is not wanted: * do not import the module * if the module is a package: recurse into the package looking for test modules make suite.TestSuite put run, call, setup, teardown, shortdescription there make LazySuite subclass it get rid of TestModule do module import in loadTestsFromModuleName; if an error, pass the error to the module suite, whose run() should re-raise the error so that import errors are seen only when we actually try to run the tests make ModuleSuite class with setUp, tearDown doing try_run, it gets additional module and error keyword args rename TestDir to DirectorySuite try to make things less stateful - conf should be immutable? - certainly conf.working_dir shouldn't change, or if it does it has to be a stack - things that are mutable should be removed from conf and passed separately tests and working dir should come out of conf and be passed to loader and selector loader.loadTestsFromNames(names, module=None, working_dir=None) -> split and absolutize all of the test names -> give them to the selector (self.selector.tests = names) -> start walking at working_dir -> sort dirnames into test-last order -> yield loadFromName for wanted files -> ModuleSuite -> for directories: - keep descending if wanted and not a package - remove from list if not wanted - if a package, yield loadFromName for package -> ModuleSuite -> since module has a path, we need to restart the walk and call loadTestsFromNames with the path end as the working dir but we want to do that lazily, so we need to bundle up the needed information into a callable and a LazySuite loader.collectTests(working_dir, names=[]): -> yield each test suite as found suites: ModuleSuite ClassSuite TestCaseSuite GeneratorSuite GeneratorMethodSuite * proxy suite may need to be mixed in by the collector when running under test or, suite base class has a testProxy property, which if not None is called to proxy the test * module isolation plugin will break under depth-first loading. how to restore it: preImport hook - snapshot sys.modules: this is what to restore AFTER processing of the test module is complete postImport hook - snapshot sys.modules: this is what to restore BEFORE running module tests startTest - if isa module, restore postImport sys.modules snapshot stopTest - if isa module, restore preImport sys.modules snapshot