How to terminate a python 2 doctest file in the middle?
Asked Answered
F

3

5

Sometimes it can be useful to run only the first part of a large doctests file.

There are many situations when the first part breaks after a code change, I would like to run only the first part, until it passes, and then run the whole file again.

I could not yet find an easy way to do this.

Let's say I start my doctests with this file:

#!/usr/bin/env python
import doctest
doctest.testfile("scenario.rst")

And scenario.rst looks like this:

>>> 'hello world'
'hello world'

>>> exit()

>>> 'this should not be processed anymore'

... lots of lines

>>> 'this should also not be processed'

In this example I use the exit() function, to demonstrate what I mean, of course it does not work, because it is treated as an exception, which doctest happily sees as part of something it could test:

**********************************************************************
File "_scenario.rst", line 10, in _scenario.rst
Failed example:
    exit()
Exception raised:
    Traceback (most recent call last):
      File "c:\Python27\lib\doctest.py", line 1254, in __run
        compileflags, 1) in test.globs
      File "<doctest _scenario.rst[1]>", line 1, in <module>
        exit()
      File "c:\Python27\lib\site.py", line 372, in __call__
        raise SystemExit(code)
    SystemExit: None
**********************************************************************
File "_scenario.rst", line 12, in _scenario.rst
Failed example:
    'this should not be processed anymore'
Expected nothing
Got:
    'this should not be processed anymore'
**********************************************************************
1 items had failures:
   2 of   3 in _scenario.rst
***Test Failed*** 2 failures.

So how could such a doctest file be terminated in the middle?

EDIT: There is the +SKIP directive, but it skips only one line. I need something that skips the rest of the file.

Footcloth answered 19/3, 2012 at 13:37 Comment(0)
S
3
>>> raise KeyboardInterrupt

This will stop a Doctest at any point, unlike all other exceptions

Personally, I consider that a KeyboardInterrupt exception is to a doctest as a SystemExit exception is to the rest of Python.

Sidonia answered 22/8, 2013 at 15:36 Comment(2)
Thank you. So according to the sourcefile at hg.python.org/cpython/file/ab05e7dd2788/Lib/doctest.py#l1286 this is the only exception that halts the doctest.Footcloth
Behaviour may be undefined while blinkingSidonia
S
4

Here's what I do: I insert

>>> 'ERROR'

at the point where I want to stop the doctest file, and then I ask my test runner to enable the doctest.REPORT_ONLY_FIRST_FAILURE flag (with zope.testrunner it's bin/test -1).

Perhaps it would be sufficient to do

>>> 'ERROR'  # doctest: +REPORT_ONLY_FIRST_FAILURE

inside your doctest file.

Personally, I do not like doctest.testfile. I prefer to create a doctest.DocFileSuite(), combine a bunch of these into a unittest.TestSuite(), and then run them all with unittest.TextTestRunner() or something like that. And I usually add optionflags=doctest.REPORT_ONLY_FIRST_FAILURE to when I create DocFileSuite objects, since I really like this option.

Sherard answered 19/3, 2012 at 17:19 Comment(0)
S
3
>>> raise KeyboardInterrupt

This will stop a Doctest at any point, unlike all other exceptions

Personally, I consider that a KeyboardInterrupt exception is to a doctest as a SystemExit exception is to the rest of Python.

Sidonia answered 22/8, 2013 at 15:36 Comment(2)
Thank you. So according to the sourcefile at hg.python.org/cpython/file/ab05e7dd2788/Lib/doctest.py#l1286 this is the only exception that halts the doctest.Footcloth
Behaviour may be undefined while blinkingSidonia
M
0

According to this bug report there are currently 2 workarounds:

  • Replace >>> with >>
  • split the docstring, and add something like "dont_test = " in front of the second part; the string becomes part of a statement and won't be parsed.
Mesothelium answered 19/3, 2012 at 13:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.