Skip to content

Commit

Permalink
Merge pull request #111 from ev-br/run_after_collection
Browse files Browse the repository at this point in the history
BUG: run tests in a tempdir, copy needed local files
  • Loading branch information
ev-br authored Feb 26, 2024
2 parents 33e85a4 + 19f3534 commit 27b6521
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 100 deletions.
61 changes: 8 additions & 53 deletions scpdt/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,10 @@

from scpdt.impl import DTChecker, DTParser, DebugDTRunner
from scpdt.conftest import dt_config
from scpdt.util import np_errstate, matplotlib_make_nongui
from scpdt.util import np_errstate, matplotlib_make_nongui, temp_cwd
from scpdt.frontend import find_doctests


copied_files = []


def pytest_configure(config):
"""
Perform initial configuration for the pytest plugin.
Expand All @@ -33,20 +30,6 @@ def pytest_configure(config):
pydoctest.DoctestTextfile = DTTextfile


def pytest_unconfigure(config):
"""
Called before exiting the test process.
"""

# Delete all locally copied files in the current working directory
if copied_files:
try:
for filepath in copied_files:
os.remove(filepath)
except FileNotFoundError:
pass


def pytest_ignore_collect(collection_path, config):
"""
Determine whether to ignore the specified collection path.
Expand Down Expand Up @@ -105,31 +88,6 @@ def pytest_collection_modifyitems(config, items):

# Replace the original list of test items with the unique ones
items[:] = unique_items


def copy_local_files(local_resources, destination_dir):
"""
Copy necessary local files for doctests to the current working directory.
This function copies files specified in the `local_resources` attribute of a DTConfig instance
to the specified `destination_dir`.
Args:
local_resources (dict): A dictionary of resources to be copied.
destination_dir (str): The destination directory where files will be copied.
Returns:
list: A list of paths to the copied files.
"""
for value in local_resources.values():
for filepath in value:
basename = os.path.basename(filepath)
dest_path = os.path.join(destination_dir, basename)

if not os.path.exists(dest_path):
shutil.copy(filepath, destination_dir)
copied_files.append(dest_path)
return copied_files


class DTModule(DoctestModule):
Expand Down Expand Up @@ -164,10 +122,6 @@ def collect(self):
else:
raise

# Copy local files specified by the `local_resources` attribute to the current working directory
if self.config.dt_config.local_resources:
copy_local_files(self.config.dt_config.local_resources, os.getcwd())

optionflags = dt_config.optionflags

# Plug in the custom runner: `PytestDTRunner`
Expand Down Expand Up @@ -208,10 +162,6 @@ def collect(self):

optionflags = pydoctest.get_optionflags(self)

# Copy local files specified by the `local_resources` attribute to the current working directory
if self.config.dt_config.local_resources:
copy_local_files(self.config.dt_config.local_resources, os.getcwd())

# Plug in the custom runner: `PytestDTRunner`
runner = _get_runner(self.config,
verbose=False,
Expand Down Expand Up @@ -254,10 +204,15 @@ def run(self, test, compileflags=None, out=None, clear_globs=False):
*unless* the `mpl()` context mgr has a chance to filter them out
*before* they become errors in `config.user_context_mgr()`.
"""
dt_config = config.dt_config


with np_errstate():
with config.dt_config.user_context_mgr(test):
with dt_config.user_context_mgr(test):
with matplotlib_make_nongui():
super().run(test, compileflags=compileflags, out=out, clear_globs=clear_globs)
# XXX: local_resourses needed? they seem to be, w/o pytest
with temp_cwd(test, dt_config.local_resources):
super().run(test, compileflags=compileflags, out=out, clear_globs=clear_globs)

"""
Almost verbatim copy of `_pytest.doctest.PytestDoctestRunner` except we utilize
Expand Down
12 changes: 6 additions & 6 deletions scpdt/tests/local_file_cases.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
from scpdt.conftest import dt_config


# Specify local files required by doctests
dt_config.local_resources = {'scpdt.tests.local_file_cases.local_files':
['scpdt/tests/local_file.txt'],
'scpdt.tests.local_file_cases.sio':
['scpdt/tests/octave_a.mat']
}
dt_config.local_resources = {
'scpdt.tests.local_file_cases.local_files': ['local_file.txt'],
'scpdt.tests.local_file_cases.sio': ['octave_a.mat']
}


__all__ = ['local_files', 'sio']


def local_files():
"""
A doctest that tries to read a local file
Expand Down
46 changes: 6 additions & 40 deletions scpdt/tests/test_pytest_configuration.py
Original file line number Diff line number Diff line change
@@ -1,48 +1,17 @@
import pytest
import os
from pathlib import PosixPath, Path

from . import module_cases, failure_cases, failure_cases_2, stopwords_cases, local_file_cases
from scpdt.plugin import copy_local_files
from scpdt.conftest import dt_config

pytest_plugins = ['pytester']


@pytest.fixture(autouse=True)
def copy_files():
"""
Copy necessary local files for doctests to the temporary directory used by pytester.
The files to be copied are defined by the `local_resources` attribute of a DTConfig instance.
When testing is done, all copied files are deleted.
"""
try:
dirname = os.path.dirname(Path(__file__))
# XXX: this is a bit hacky and repetetive. Can rework?

# Update the file path of each filename
for value in dt_config.local_resources.values():
for i, path in enumerate(value):
value[i] = os.path.join(dirname, os.path.basename(path))

# Copy the files
copied_files = copy_local_files(dt_config.local_resources, os.getcwd())

yield copied_files

finally:
# Perform clean-up
for filepath in copied_files:
try:
os.remove(filepath)
except FileNotFoundError:
pass

pytest_plugins = ['pytester']

"""
Test that pytest uses the DTChecker for doctests
"""

def test_module_cases(pytester):
"""Test that pytest uses the DTChecker for doctests."""
path_str = module_cases.__file__
python_file = PosixPath(path_str)
result = pytester.inline_run(python_file, "--doctest-modules")
Expand All @@ -58,20 +27,17 @@ def test_failure_cases(pytester):
assert result.ret == pytest.ExitCode.TESTS_FAILED


"""
Test that pytest uses the DTParser for doctests
"""
def test_stopword_cases(pytester):
"""Test that pytest uses the DTParser for doctests."""
path_str = stopwords_cases.__file__
python_file = PosixPath(path_str)
result = pytester.inline_run(python_file, "--doctest-modules")
assert result.ret == pytest.ExitCode.OK


"""
Test that local files are found for use in doctests
"""
def test_local_file_cases(pytester):
"""Test that local files are found for use in doctests.
"""
path_str = local_file_cases.__file__
python_file = PosixPath(path_str)
result = pytester.inline_run(python_file, "--doctest-modules")
Expand Down
2 changes: 1 addition & 1 deletion scpdt/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def temp_cwd(test, local_resources=None):
# local files requested; copy the files
path, _ = os.path.split(test.filename)
for fname in local_resources[test.name]:
shutil.copy(os.path.join(path, fname), tmpdir)
shutil.copy(os.path.join(path, fname), tmpdir)
try:
os.chdir(tmpdir)
yield tmpdir
Expand Down

0 comments on commit 27b6521

Please sign in to comment.