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