Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Running doctest prevents complete coverage collection #575

Closed
nedbat opened this issue May 1, 2017 · 6 comments
Closed

Running doctest prevents complete coverage collection #575

nedbat opened this issue May 1, 2017 · 6 comments
Labels
bug Something isn't working run

Comments

@nedbat
Copy link
Owner

nedbat commented May 1, 2017

sample.py:

#!python

import doctest

TEST = """
>>> x = 1
>>> x
1
"""

doctest.run_docstring_examples(TEST, {})

q = 11
r = 12

Running coverage leaves the last two lines unmeasured:

$ coverage run sample.py && coverage report -m
Name        Stmts   Miss  Cover   Missing
-----------------------------------------
sample.py       5      2    60%   11-12

Switching from the C tracer to the Python tracer fixes it:

$ coverage run --timid sample.py && coverage report -m
Name        Stmts   Miss  Cover   Missing
-----------------------------------------
sample.py       5      0   100%

The problem only appears in Python 3. It's due to the sys.settrace in the finally clause in this commit: python/cpython@31f5929, which was to fix this bug: http://bugs.python.org/issue10990

There seems to be something wrong with getting and restoring the C trace function. (Odd though, since there are tests that check this...)


@nedbat
Copy link
Owner Author

nedbat commented May 1, 2017

Thanks to @chriswithers for the original report.

@nedbat
Copy link
Owner Author

nedbat commented May 2, 2017

A simpler reproducer, with no doctest:

sample.py:

from swap import swap_it

print(3)
swap_it()
print(5)

swap.py:

import sys

def swap_it():
    no_really()

def no_really():
    save_trace = sys.gettrace()
    sys.settrace(save_trace)

Three runs:

$ coverage run sample.py && coverage report -m
3
5
Name        Stmts   Miss  Cover   Missing
-----------------------------------------
sample.py       4      0   100%
swap.py         6      0   100%
-----------------------------------------
TOTAL          10      0   100%
$ coverage run --source=sample sample.py && coverage report -m
3
5
Name        Stmts   Miss  Cover   Missing
-----------------------------------------
sample.py       4      1    75%   5
$ coverage run --source=sample --timid sample.py && coverage report -m
3
5
Name        Stmts   Miss  Cover   Missing
-----------------------------------------
sample.py       4      0   100%

I'm not sure why --source changes the behavior. Also, if the settrace(gettrace) happens in sample.py, then the problem doesn't happen. All of this is the same on Python 2.7 and Python 3.6 (the py3 claim above is because of changes in doctest).

@nedbat
Copy link
Owner Author

nedbat commented May 2, 2017

More details as they dribble in: this also happens with coverage.py 3.7.1.

Seems that if the file that does the settrace(gettrace) isn't being traced itself, the problem happens. This is why it happens with doctest, and with my own file without --source.

@nedbat
Copy link
Owner Author

nedbat commented May 2, 2017

Fixed in 03b48c292790 (bb)

@nedbat
Copy link
Owner Author

nedbat commented May 2, 2017

Original comment by Chris Withers (Bitbucket: chrisw, GitHub: chrisw)


Fun times, thanks Ned! Glad you fight this craziness so the rest of us don't have to ;-)
When's 4.4 due out?

@nedbat
Copy link
Owner Author

nedbat commented May 3, 2017

I'm aiming for within a week.

@nedbat nedbat closed this as completed May 3, 2017
@nedbat nedbat added minor bug Something isn't working run labels Jun 23, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working run
Projects
None yet
Development

No branches or pull requests

1 participant