From 9ca7e46a0ac57c080ed81fa817a5fc6bbc19743a Mon Sep 17 00:00:00 2001 From: Holger Peters Date: Wed, 8 Oct 2014 14:31:17 +0200 Subject: [PATCH 1/4] Add configuration option for doctest flags --- _pytest/doctest.py | 28 ++++++++++++++++++++++++++-- testing/test_doctest.py | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/_pytest/doctest.py b/_pytest/doctest.py index f61730717..729c65b7f 100644 --- a/_pytest/doctest.py +++ b/_pytest/doctest.py @@ -6,6 +6,8 @@ from _pytest.python import FixtureRequest, FuncFixtureInfo from py._code.code import TerminalRepr, ReprFileLocation def pytest_addoption(parser): + parser.addini('doctest_optionflags', 'option flags for doctests', + type="args", default=["ELLIPSIS"]) group = parser.getgroup("collect") group.addoption("--doctest-modules", action="store_true", default=False, @@ -87,6 +89,27 @@ class DoctestItem(pytest.Item): def reportinfo(self): return self.fspath, None, "[doctest] %s" % self.name +def _get_flag_lookup(): + import doctest + return dict(DONT_ACCEPT_TRUE_FOR_1=doctest.DONT_ACCEPT_TRUE_FOR_1, + DONT_ACCEPT_BLANKLINE=doctest.DONT_ACCEPT_BLANKLINE, + NORMALIZE_WHITESPACE=doctest.NORMALIZE_WHITESPACE, + ELLIPSIS=doctest.ELLIPSIS, + IGNORE_EXCEPTION_DETAIL=doctest.IGNORE_EXCEPTION_DETAIL, + COMPARISON_FLAGS=doctest.COMPARISON_FLAGS) + +def get_optionflags(parent): + import doctest + optionflags_str = parent.config.getini("doctest_optionflags") + flag_lookup_table = _get_flag_lookup() + if not optionflags_str: + return doctest.ELLIPSIS + + flag_acc = 0 + for flag in optionflags_str: + flag_acc |= flag_lookup_table[flag] + return flag_acc + class DoctestTextfile(DoctestItem, pytest.File): def runtest(self): import doctest @@ -101,7 +124,7 @@ class DoctestTextfile(DoctestItem, pytest.File): fixture_request._fillfixtures() failed, tot = doctest.testfile( str(self.fspath), module_relative=False, - optionflags=doctest.ELLIPSIS, + optionflags=get_optionflags(self), extraglobs=dict(getfixture=fixture_request.getfuncargvalue), raise_on_error=True, verbose=0) @@ -119,7 +142,8 @@ class DoctestModule(pytest.File): doctest_globals = dict(getfixture=fixture_request.getfuncargvalue) # uses internal doctest module parsing mechanism finder = doctest.DocTestFinder() - runner = doctest.DebugRunner(verbose=0, optionflags=doctest.ELLIPSIS) + optionflags= get_optionflags(self) + runner = doctest.DebugRunner(verbose=0, optionflags=optionflags) for test in finder.find(module, module.__name__, extraglobs=doctest_globals): if test.examples: # skip empty doctests diff --git a/testing/test_doctest.py b/testing/test_doctest.py index c6c05a45d..d33f61150 100644 --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -289,3 +289,37 @@ class TestDoctests: """) reprec = testdir.inline_run(p, "--doctest-modules") reprec.assertoutcome(failed=1, passed=1) + + def test_ignored_whitespace(self, testdir): + testdir.makeini(""" + [pytest] + doctest_optionflags = ELLIPSIS NORMALIZE_WHITESPACE + """) + p = testdir.makepyfile(""" + class MyClass: + ''' + >>> a = "foo " + >>> print(a) + foo + ''' + pass + """) + reprec = testdir.inline_run(p, "--doctest-modules") + reprec.assertoutcome(passed=1) + + def test_non_ignored_whitespace(self, testdir): + testdir.makeini(""" + [pytest] + doctest_optionflags = ELLIPSIS + """) + p = testdir.makepyfile(""" + class MyClass: + ''' + >>> a = "foo " + >>> print(a) + foo + ''' + pass + """) + reprec = testdir.inline_run(p, "--doctest-modules") + reprec.assertoutcome(failed=1, passed=0) From 1de5af66daacb9274f1533bcdcef5a749ab4b001 Mon Sep 17 00:00:00 2001 From: Holger Peters Date: Wed, 8 Oct 2014 15:48:41 +0200 Subject: [PATCH 2/4] Add documentation for doctest flags and remove dead code --- CHANGELOG | 2 ++ _pytest/doctest.py | 3 --- doc/en/customize.txt | 5 +++++ doc/en/doctest.txt | 9 +++++++++ 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 83f63601c..010154117 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,8 @@ Unreleased ---------- +- add a doctest option for doctest flags + - Improve assertion failure reporting on iterables, by using ndiff and pprint. - removed outdated japanese docs from source tree. diff --git a/_pytest/doctest.py b/_pytest/doctest.py index 729c65b7f..2dd8706ad 100644 --- a/_pytest/doctest.py +++ b/_pytest/doctest.py @@ -102,9 +102,6 @@ def get_optionflags(parent): import doctest optionflags_str = parent.config.getini("doctest_optionflags") flag_lookup_table = _get_flag_lookup() - if not optionflags_str: - return doctest.ELLIPSIS - flag_acc = 0 for flag in optionflags_str: flag_acc |= flag_lookup_table[flag] diff --git a/doc/en/customize.txt b/doc/en/customize.txt index ac263b1fa..ab7cda79f 100644 --- a/doc/en/customize.txt +++ b/doc/en/customize.txt @@ -126,3 +126,8 @@ Builtin configuration file options derived class. See :ref:`change naming conventions` for examples. + +.. confval:: doctest_optionflags + + One or more doctest flag names from the standard ``doctest`` module. + `See how py.test handles doctests `_. diff --git a/doc/en/doctest.txt b/doc/en/doctest.txt index c612d9a23..000aa1653 100644 --- a/doc/en/doctest.txt +++ b/doc/en/doctest.txt @@ -60,3 +60,12 @@ It is possible to use fixtures using the ``getfixture`` helper:: Also, :ref:`usefixtures` and :ref:`autouse` fixtures are supported when executing text doctest files. + +The standard ``doctest`` module provides some setting flags to configure the +strictness of doctest tests. In py.test You can enable those flags those flags +using the configuration file. To make pytest ignore trailing whitespaces and +ignore lengthy exception stack traces you can just write:: + + # content of pytest.ini + [pytest] + doctest_optionflags= NORMALIZE_WHITESPACE IGNORE_EXCEPTION_DETAIL From bf2f2dc2a64ce080244fa4abb2a7ace039af6c9b Mon Sep 17 00:00:00 2001 From: Holger Peters Date: Wed, 8 Oct 2014 15:54:08 +0200 Subject: [PATCH 3/4] Add a doctest for module docstrings --- testing/test_doctest.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/testing/test_doctest.py b/testing/test_doctest.py index d33f61150..aa1795874 100644 --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -323,3 +323,29 @@ class TestDoctests: """) reprec = testdir.inline_run(p, "--doctest-modules") reprec.assertoutcome(failed=1, passed=0) + + def test_ignored_whitespace_glob(self, testdir): + testdir.makeini(""" + [pytest] + doctest_optionflags = ELLIPSIS NORMALIZE_WHITESPACE + """) + p = testdir.maketxtfile(xdoc=""" + >>> a = "foo " + >>> print(a) + foo + """) + reprec = testdir.inline_run(p, "--doctest-glob=x*.txt") + reprec.assertoutcome(passed=1) + + def test_non_ignored_whitespace_glob(self, testdir): + testdir.makeini(""" + [pytest] + doctest_optionflags = ELLIPSIS + """) + p = testdir.maketxtfile(xdoc=""" + >>> a = "foo " + >>> print(a) + foo + """) + reprec = testdir.inline_run(p, "--doctest-glob=x*.txt") + reprec.assertoutcome(failed=1, passed=0) From e1a66d54b92f6fba685d5f8b9703f2a4a1a72f41 Mon Sep 17 00:00:00 2001 From: Holger Peters Date: Thu, 9 Oct 2014 16:59:42 +0200 Subject: [PATCH 4/4] link fix: Use restructured text :doc: link instead of html link --- doc/en/customize.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/customize.txt b/doc/en/customize.txt index ab7cda79f..bea6f1dee 100644 --- a/doc/en/customize.txt +++ b/doc/en/customize.txt @@ -130,4 +130,4 @@ Builtin configuration file options .. confval:: doctest_optionflags One or more doctest flag names from the standard ``doctest`` module. - `See how py.test handles doctests `_. + :doc:`See how py.test handles doctests `.