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

BUG: run tests in a tempdir, copy needed local files #111

Merged
merged 3 commits into from
Feb 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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):
ev-br marked this conversation as resolved.
Show resolved Hide resolved
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
Loading