-
-
Notifications
You must be signed in to change notification settings - Fork 5
Run tests in context managers #87
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
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
4a71b67
run tests in context managers
Sheila-nk 2211869
create special runner to run tests in contexts and handle reporting
Sheila-nk eacfc08
use config attribute
Sheila-nk af12312
clean up
Sheila-nk 72b10b2
pass clear_globs as is
Sheila-nk File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,4 +8,4 @@ | |
['scpdt/tests/local_file.txt'], | ||
'scpdt.tests.local_file_cases.sio': | ||
['scpdt/tests/octave_a.mat'] | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,19 @@ | ||
""" | ||
A pytest plugin that provides enhanced doctesting for Pydata libraries | ||
""" | ||
import bdb | ||
import os | ||
import shutil | ||
|
||
from _pytest import doctest | ||
from _pytest import doctest, outcomes | ||
from _pytest.doctest import DoctestModule, DoctestTextfile | ||
from _pytest.pathlib import import_path | ||
from _pytest.outcomes import skip | ||
from _pytest.outcomes import skip, OutcomeException | ||
|
||
from scpdt.impl import DTChecker, DTParser, DTFinder | ||
from scpdt.impl import DTChecker, DTParser, DTFinder, DebugDTRunner | ||
from scpdt.conftest import dt_config | ||
from .util import np_errstate, matplotlib_make_nongui | ||
|
||
|
||
copied_files = [] | ||
|
||
|
@@ -19,6 +22,7 @@ def pytest_configure(config): | |
Allow plugins and conftest files to perform initial configuration. | ||
""" | ||
|
||
doctest._get_runner = _get_runner | ||
doctest._get_checker = _get_checker | ||
doctest.DoctestModule = DTModule | ||
doctest.DoctestTextfile = DTTextfile | ||
|
@@ -39,7 +43,7 @@ def pytest_unconfigure(config): | |
|
||
def _get_checker(): | ||
""" | ||
Override function to return an instance of DTChecker with default configurations | ||
Override function to return an instance of DTChecker | ||
""" | ||
return DTChecker(config=dt_config) | ||
|
||
|
@@ -99,16 +103,16 @@ def collect(self): | |
# We plugin scpdt's `DTFinder` that uses the `DTParser` which parses the doctest examples | ||
# from the python module or file and filters out stopwords and pseudocode. | ||
finder = DTFinder(config=dt_config) | ||
|
||
# the rest remains unchanged | ||
optionflags = doctest.get_optionflags(self) | ||
runner = doctest._get_runner( | ||
|
||
# We plug in `PytestDTRunner` | ||
runner = _get_runner( | ||
verbose=False, | ||
optionflags=optionflags, | ||
checker=_get_checker(), | ||
continue_on_failure=doctest._get_continue_on_failure(self.config), | ||
checker=_get_checker() | ||
) | ||
|
||
# the rest remains unchanged | ||
for test in finder.find(module, module.__name__): | ||
if test.examples: # skip empty doctests | ||
yield doctest.DoctestItem.from_parent( | ||
|
@@ -138,11 +142,11 @@ def collect(self): | |
if dt_config.local_resources: | ||
copy_local_files(dt_config.local_resources, os.getcwd()) | ||
|
||
runner = doctest._get_runner( | ||
# We plug in `PytestDTRunner` | ||
runner = _get_runner( | ||
verbose=False, | ||
optionflags=optionflags, | ||
checker=_get_checker(), | ||
continue_on_failure=doctest._get_continue_on_failure(self.config) | ||
checker=_get_checker() | ||
) | ||
|
||
# We plug in an instance of `DTParser` which parses the doctest examples from the text file and | ||
|
@@ -159,6 +163,55 @@ def collect(self): | |
|
||
def _get_parser(): | ||
""" | ||
Return instance of DTParser with default configuration | ||
Return instance of DTParser | ||
Please refer to `testmod` source for a discussion of the order of context managers. | ||
""" | ||
return DTParser(config=dt_config) | ||
|
||
|
||
def _get_runner(checker, verbose, optionflags): | ||
import doctest | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: there is probably no reason to hide imports; move it to the module level. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's because of this error: AttributeError: module '_pytest.doctest' has no attribute 'UnexpectedException' |
||
""" | ||
Override function to return instance of PytestDTRunner | ||
""" | ||
return DTParser(config=dt_config) | ||
class PytestDTRunner(DebugDTRunner): | ||
def run(self, test, compileflags=None, out=None, clear_globs=False): | ||
""" | ||
Run tests in context managers. | ||
Restore the errstate/print state after each docstring. | ||
Also make MPL backend non-GUI and close the figures. | ||
The order of context managers is actually relevant. Consider | ||
user_context_mgr that turns warnings into errors. | ||
Additionally, suppose that MPL deprecates something and plt.something | ||
starts issuing warngings. Now all of those become errors | ||
*unless* the `mpl()` context mgr has a chance to filter them out | ||
*before* they become errors in `config.user_context_mgr()`. | ||
""" | ||
Sheila-nk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
with np_errstate(): | ||
with dt_config.user_context_mgr(test): | ||
with matplotlib_make_nongui(): | ||
super().run(test, compileflags=compileflags, out=out, clear_globs=clear_globs) | ||
|
||
""" | ||
Almost verbatim copy of `_pytest.doctest.PytestDoctestRunner` except we utilize | ||
DTConfig's `nameerror_after_exception` attribute in place of doctest's `continue_on_failure`. | ||
""" | ||
def report_failure(self, out, test, example, got): | ||
failure = doctest.DocTestFailure(test, example, got) | ||
if dt_config.nameerror_after_exception: | ||
out.append(failure) | ||
else: | ||
raise failure | ||
|
||
def report_unexpected_exception(self, out, test, example, exc_info): | ||
if isinstance(exc_info[1], OutcomeException): | ||
raise exc_info[1] | ||
if isinstance(exc_info[1], bdb.BdbQuit): | ||
outcomes.exit("Quitting debugger") | ||
failure = doctest.UnexpectedException(test, example, exc_info) | ||
if dt_config.nameerror_after_exception: | ||
out.append(failure) | ||
else: | ||
raise failure | ||
|
||
return PytestDTRunner(checker=checker, verbose=verbose, optionflags=optionflags, config=dt_config) |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why are we dropping continue_on_failure?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
continue_on_failure
is a pytest ini option. Figured it would be best to useDTConfig's
nameerror_after_exception
attribute instead since both do the same thing.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#87 (comment) please make sure that this test passes with the plugin