-- 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
