diff --git a/tests/roots/test-ext-doctest-skipif/conf.py b/tests/roots/test-ext-doctest-skipif/conf.py new file mode 100644 index 000000000..5f3e89786 --- /dev/null +++ b/tests/roots/test-ext-doctest-skipif/conf.py @@ -0,0 +1,10 @@ +extensions = ['sphinx.ext.doctest'] + +project = 'test project for the doctest :skipif: directive' +master_doc = 'skipif' +source_suffix = '.txt' +exclude_patterns = ['_build'] + +doctest_global_setup = ''' +from test_ext_doctest import record +''' \ No newline at end of file diff --git a/tests/roots/test-ext-doctest-skipif/skipif.txt b/tests/roots/test-ext-doctest-skipif/skipif.txt new file mode 100644 index 000000000..c5bd39821 --- /dev/null +++ b/tests/roots/test-ext-doctest-skipif/skipif.txt @@ -0,0 +1,81 @@ +Testing the doctest extension's `:skipif:` option +================================================= + +testsetup +--------- + +.. testsetup:: group-skipif + :skipif: record('testsetup', ':skipif:', True) != 'this will be True' + + record('testsetup', 'body', True) + +.. testsetup:: group-skipif + :skipif: record('testsetup', ':skipif:', False) == 'this will be False' + + record('testsetup', 'body', False) + + +doctest +------- +.. doctest:: group-skipif + :skipif: record('doctest', ':skipif:', True) != 'this will be True' + + >>> print(record('doctest', 'body', True)) + The test is skipped, and this expected text is ignored + + +.. doctest:: + :skipif: record('doctest', ':skipif:', False) == 'this will be False' + + >>> print(record('doctest', 'body', False)) + Recorded doctest body False + + +testcode and testoutput +----------------------- + +testcode skipped +~~~~~~~~~~~~~~~~ + +.. testcode:: group-skipif + :skipif: record('testcode', ':skipif:', True) != 'this will be True' + + print(record('testcode', 'body', True)) + +.. testoutput:: group-skipif + :skipif: record('testoutput-1', ':skipif:', True) != 'this will be True' + + The previous testcode is skipped, and the :skipif: condition is True, + so this testoutput is ignored + +testcode executed +~~~~~~~~~~~~~~~~~ + +.. testcode:: group-skipif + :skipif: record('testcode', ':skipif:', False) == 'this will be False' + + print(record('testcode', 'body', False)) + +.. testoutput:: group-skipif + :skipif: record('testoutput-2', ':skipif:', False) == 'this will be False' + + Recorded testcode body False + +.. testoutput:: group-skipif + :skipif: record('testoutput-2', ':skipif:', True) != 'this will be True' + + The :skipif: condition is False, so this testoutput is ignored + + +testcleanup +----------- + +.. testcleanup:: group-skipif + :skipif: record('testcleanup', ':skipif:', True) != 'this will be True' + + record('testcleanup', 'body', True) + +.. testcleanup:: group-skipif + :skipif: record('testcleanup', ':skipif:', False) == 'this will be False' + + record('testcleanup', 'body', False) diff --git a/tests/test_ext_doctest.py b/tests/test_ext_doctest.py index 7137af31b..5ae3c0f7a 100644 --- a/tests/test_ext_doctest.py +++ b/tests/test_ext_doctest.py @@ -61,6 +61,51 @@ def cleanup_call(): cleanup_called += 1 +recorded_calls = set() + + +@pytest.mark.sphinx('doctest', testroot='ext-doctest-skipif') +def test_skipif(app, status, warning): + """Tests for the :skipif: option + + The tests are separated into a different test root directory since the + ``app`` object only evaluates options once in its lifetime. If these tests + were combined with the other doctest tests, the ``:skipif:`` evaluations + would be recorded only on the first ``app.builder.build_all()`` run, i.e. + in ``test_build`` above, and the assertion below would fail. + + """ + global recorded_calls + recorded_calls = set() + app.builder.build_all() + if app.statuscode != 0: + assert False, 'failures in doctests:' + status.getvalue() + # The `:skipif:` expressions are always run. + # Actual tests and setup/cleanup code is only run if the `:skipif:` + # expression evaluates to a False value. + assert recorded_calls == {('testsetup', ':skipif:', True), + ('testsetup', ':skipif:', False), + ('testsetup', 'body', False), + ('doctest', ':skipif:', True), + ('doctest', ':skipif:', False), + ('doctest', 'body', False), + ('testcode', ':skipif:', True), + ('testcode', ':skipif:', False), + ('testcode', 'body', False), + ('testoutput-1', ':skipif:', True), + ('testoutput-2', ':skipif:', True), + ('testoutput-2', ':skipif:', False), + ('testcleanup', ':skipif:', True), + ('testcleanup', ':skipif:', False), + ('testcleanup', 'body', False)} + + +def record(directive, part, should_skip): + global recorded_calls + recorded_calls.add((directive, part, should_skip)) + return 'Recorded {} {} {}'.format(directive, part, should_skip) + + @pytest.mark.xfail( PY2, reason='node.source points to document instead of filename', )