diff options
-rw-r--r-- | TODO | 8 | ||||
-rw-r--r-- | functional_tests/support/dtt/docs/doc.txt | 6 | ||||
-rw-r--r-- | functional_tests/support/dtt/docs/errdoc.txt | 7 | ||||
-rw-r--r-- | functional_tests/support/dtt/docs/nodoc.txt | 1 | ||||
-rw-r--r-- | functional_tests/test_doctest_plugin.py | 20 | ||||
-rw-r--r-- | nose/loader.py | 7 | ||||
-rw-r--r-- | nose/plugins/base.py | 24 | ||||
-rw-r--r-- | nose/plugins/doctests.py | 29 | ||||
-rw-r--r-- | nose/plugins/manager.py | 3 | ||||
-rw-r--r-- | unit_tests/test_doctest_error_handling.py | 10 | ||||
-rw-r--r-- | unit_tests/test_plugins.py | 1 |
11 files changed, 75 insertions, 41 deletions
@@ -16,7 +16,7 @@ add --plugins option displays loadable plugins, with version (if applicable), score, description for each. options for each also if verbosity >= 2 -make sure lib-first collection is still working (dir contents sorted test-last) +** make sure lib-first collection is still working (dir contents sorted test-last) rename Failure and split into subclasses for Import and other, and make it optionally include the name of the file being considered so that @@ -65,9 +65,9 @@ TESTS NEEDED arguments testid -- needs tests with doctests - -- doctests from non module files - doctest - -- needs tests from non-module files + ** -- doctests from non module files + ** doctest + ** -- needs tests from non-module files coverage/doctest -- need tests for coverage/doctest interaction diff --git a/functional_tests/support/dtt/docs/doc.txt b/functional_tests/support/dtt/docs/doc.txt new file mode 100644 index 0000000..4cf3955 --- /dev/null +++ b/functional_tests/support/dtt/docs/doc.txt @@ -0,0 +1,6 @@ +This document is a doctest. + + >>> 1 + 1 + 2 + +That's all diff --git a/functional_tests/support/dtt/docs/errdoc.txt b/functional_tests/support/dtt/docs/errdoc.txt new file mode 100644 index 0000000..a947b52 --- /dev/null +++ b/functional_tests/support/dtt/docs/errdoc.txt @@ -0,0 +1,7 @@ +This document contains an invalid doctest. + + >>> def foo(): + >>> def bar(): + ... pass + +That is all. diff --git a/functional_tests/support/dtt/docs/nodoc.txt b/functional_tests/support/dtt/docs/nodoc.txt new file mode 100644 index 0000000..665f935 --- /dev/null +++ b/functional_tests/support/dtt/docs/nodoc.txt @@ -0,0 +1 @@ +This document contains no doctests. diff --git a/functional_tests/test_doctest_plugin.py b/functional_tests/test_doctest_plugin.py index 0204eb0..c91ecc5 100644 --- a/functional_tests/test_doctest_plugin.py +++ b/functional_tests/test_doctest_plugin.py @@ -20,5 +20,25 @@ class TestDoctestPlugin(PluginTester, unittest.TestCase): assert str(self.output).strip().endswith('OK') +class TestDoctestFiles(PluginTester, unittest.TestCase): + activate = '--with-doctest' + args = ['-v', '--doctest-extension=.txt'] + plugins = [Doctest()] + suitepath = os.path.join(support, 'dtt', 'docs') + + def runTest(self): + print str(self.output) + + expect = [ + 'Doctest: doc.txt ... ok', + 'Doctest: errdoc.txt ... FAIL' + ] + for line in self.output: + if not line.strip(): + continue + if line.startswith('='): + break + self.assertEqual(line.strip(), expect.pop(0)) + if __name__ == '__main__': unittest.main() diff --git a/nose/loader.py b/nose/loader.py index 47d7c2c..66962e0 100644 --- a/nose/loader.py +++ b/nose/loader.py @@ -128,9 +128,14 @@ class TestLoader(unittest.TestLoader): tests = [test for test in self.config.plugins.loadTestsFromFile(filename)] if tests: + # Plugins can yield False to indicate that they were + # unable to load tests from a file, but it was not an + # error -- the file just had no tests to load. + tests = filter(None, tests) return self.suiteClass(tests) else: - open(filename, 'r').close() # trigger os error + # Nothing was able to even try to load from this file + open(filename, 'r').close() # trigger os error raise ValueError("Unable to load tests from file %s" % filename) except KeyboardInterrupt: diff --git a/nose/plugins/base.py b/nose/plugins/base.py index c9202bf..162dff0 100644 --- a/nose/plugins/base.py +++ b/nose/plugins/base.py @@ -506,22 +506,24 @@ class IPluginInterface(object): loadTestsFromNames._new = True loadTestsFromNames.chainable = True - def loadTestsFromPath(self, path, module=None, importPath=None): - """Return tests in this file or directory. Return None if you are not - able to load any tests, or an iterable if you are. May be a - generator. + def loadTestsFromFile(self, filename): + """Return tests in this file. Return None if you are not able + to load any tests, or an iterable if you are. May be a + generator. If you are interested in loading tests from the + file and encounter no errors, but find no tests, yield False + or return [False]. + NOTE that this method replaces loadTestsFromPath from the 0.9 + API. + Parameters: - * path: + * filename: The full path to the file or directory. - * module: - Module in which the file/dir is found - * importPath: - Path from which file (must be a python module) was found """ pass - loadTestsFromPath.generative = True - loadTestsFromFile = loadTestsFromPath + loadTestsFromFile.generative = True + loadTestsFromFile._new = True + loadTestsFromPath = loadTestsFromFile def loadTestsFromTestCase(self, cls): """Return tests in this test case class. Return None if you are diff --git a/nose/plugins/doctests.py b/nose/plugins/doctests.py index aba8790..31e027d 100644 --- a/nose/plugins/doctests.py +++ b/nose/plugins/doctests.py @@ -73,21 +73,16 @@ class Doctest(Plugin): default=env.get('NOSE_DOCTEST_TESTS'), help="Also look for doctests in test modules " "[NOSE_DOCTEST_TESTS]") - try: - # 2.4 or better supports loading tests from non-modules - doctest.DocFileSuite - parser.add_option('--doctest-extension', action="append", - dest="doctestExtension", - help="Also look for doctests in files with " - "this extension [NOSE_DOCTEST_EXTENSION]") - # Set the default as a list, if given in env; otherwise - # an additional value set on the command line will cause - # an error. - env_setting = env.get('NOSE_DOCTEST_EXTENSION') - if env_setting is not None: - parser.set_defaults(doctestExtension=tolist(env_setting)) - except AttributeError: - pass + parser.add_option('--doctest-extension', action="append", + dest="doctestExtension", + help="Also look for doctests in files with " + "this extension [NOSE_DOCTEST_EXTENSION]") + # Set the default as a list, if given in env; otherwise + # an additional value set on the command line will cause + # an error. + env_setting = env.get('NOSE_DOCTEST_EXTENSION') + if env_setting is not None: + parser.set_defaults(doctestExtension=tolist(env_setting)) def configure(self, options, config): Plugin.configure(self, options, config) @@ -130,6 +125,8 @@ class Doctest(Plugin): doc, globs={}, name=name, filename=filename, lineno=0) if test.examples: yield DocFileCase(test) + else: + yield False # no tests to load def makeTest(self, obj, parent): """Look for doctests in the given object, which will be a @@ -220,4 +217,4 @@ class DocFileCase(doctest.DocFileCase): """Overrides to provide filename """ def address(self): - return (self._dt_test_filename, None, None) + return (self._dt_test.filename, None, None) diff --git a/nose/plugins/manager.py b/nose/plugins/manager.py index 2af973a..7cf1052 100644 --- a/nose/plugins/manager.py +++ b/nose/plugins/manager.py @@ -189,7 +189,8 @@ class ZeroNinePlugin: capt = test.capturedOutput return self.plugin.addError(test.test, err, capt) - # FIXME loadTestsFromFile -> loadTestsFromPath + def loadTestsFromFile(self, filename): + return self.plugin.loadTestsFromPath(filename) def addFailure(self, test, err): if not hasattr(self.plugin, 'addFailure'): diff --git a/unit_tests/test_doctest_error_handling.py b/unit_tests/test_doctest_error_handling.py index 0b0fd5e..fcdf388 100644 --- a/unit_tests/test_doctest_error_handling.py +++ b/unit_tests/test_doctest_error_handling.py @@ -5,9 +5,6 @@ from nose.config import Config from nose.plugins import doctests from mock import Bucket -# some plugins have 2.4-only features -compat_24 = sys.version_info >= (2, 4) - class TestDoctestErrorHandling(unittest.TestCase): def setUp(self): @@ -37,10 +34,7 @@ class TestDoctestErrorHandling(unittest.TestCase): except ValueError: pass else: - if compat_24: - self.fail("Error doctests file did not raise ValueError") - else: - self.assert_(loaded, - "No value error, nothing loaded from err tests") + self.fail("Error doctests file did not raise ValueError") + if __name__ == '__main__': unittest.main() diff --git a/unit_tests/test_plugins.py b/unit_tests/test_plugins.py index 3401afa..c41f14e 100644 --- a/unit_tests/test_plugins.py +++ b/unit_tests/test_plugins.py @@ -187,6 +187,7 @@ class TestDoctestPlugin(unittest.TestCase): suite = plug.loadTestsFromFile(fn) for test in suite: assert str(test).endswith('doctests.txt') + assert test.address(), "Test %s has no address" def test_collect_no_collect(self): # bug http://nose.python-hosting.com/ticket/55 |