Skip to content

Commit

Permalink
feat(fixtures): add use_pandas pytest fixture and --pandas CLI arg (#112
Browse files Browse the repository at this point in the history
)
  • Loading branch information
wpbonelli committed Sep 12, 2023
1 parent b8ee2e3 commit a41caa7
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 24 deletions.
40 changes: 31 additions & 9 deletions modflow_devtools/fixtures.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import random
from collections import OrderedDict
from itertools import groupby
from os import PathLike, environ
Expand All @@ -10,7 +11,8 @@

pytest = import_optional_dependency("pytest")

# temporary directory fixtures

# fixtures


@pytest.fixture(scope="function")
Expand All @@ -23,7 +25,7 @@ def function_tmpdir(tmpdir_factory, request) -> Path:
temp = Path(tmpdir_factory.mktemp(node))
yield Path(temp)

keep = request.config.getoption("--keep")
keep = request.config.option.KEEP
if keep:
path = Path(keep) / temp.name
if path.is_dir():
Expand All @@ -46,7 +48,7 @@ def class_tmpdir(tmpdir_factory, request) -> Path:
temp = Path(tmpdir_factory.mktemp(request.cls.__name__))
yield temp

keep = request.config.getoption("--keep")
keep = request.config.option.KEEP
if keep:
path = Path(keep) / temp.name
if path.is_dir():
Expand All @@ -59,7 +61,7 @@ def module_tmpdir(tmpdir_factory, request) -> Path:
temp = Path(tmpdir_factory.mktemp(request.module.__name__))
yield temp

keep = request.config.getoption("--keep")
keep = request.config.option.KEEP
if keep:
path = Path(keep) / temp.name
if path.is_dir():
Expand All @@ -72,24 +74,34 @@ def session_tmpdir(tmpdir_factory, request) -> Path:
temp = Path(tmpdir_factory.mktemp(request.session.name))
yield temp

keep = request.config.getoption("--keep")
keep = request.config.option.KEEP
if keep:
path = Path(keep) / temp.name
if path.is_dir():
rmtree(path)
copytree(temp, path)


# environment-dependent fixtures


@pytest.fixture
def repos_path() -> Optional[Path]:
"""Path to directory containing test model and example repositories"""
return environ.get("REPOS_PATH", None)


# pytest configuration hooks
@pytest.fixture
def use_pandas(request):
pandas = request.config.option.PANDAS
if pandas == "yes":
return True
elif pandas == "no":
return False
elif pandas == "random":
return random.randint(0, 1) == 0
else:
raise ValueError(f"Unsupported value for --pandas: {pandas}")


# configuration hooks


def pytest_addoption(parser):
Expand All @@ -98,6 +110,7 @@ def pytest_addoption(parser):
"--keep",
action="store",
default=None,
dest="KEEP",
help="Move the contents of temporary test directories to correspondingly named subdirectories at the given "
"location after tests complete. This option can be used to exclude test results from automatic cleanup, "
"e.g. for manual inspection. The provided path is created if it does not already exist. An error is "
Expand Down Expand Up @@ -144,6 +157,15 @@ def pytest_addoption(parser):
help="Select a subset of packages to run.",
)

parser.addoption(
"-P",
"--pandas",
action="store",
default="yes",
dest="PANDAS",
help="Package input data can be provided as either pandas dataframes or numpy recarrays. By default, pandas dataframes are used. To test with numpy recarrays, use 'no'. To randomize selection (per test), use 'random'.",
)


def pytest_configure(config):
config.addinivalue_line(
Expand Down
73 changes: 58 additions & 15 deletions modflow_devtools/test/test_fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,18 +47,18 @@ def test_function_scoped_tmpdir_slash_in_name(function_tmpdir, name):


class TestClassScopedTmpdir:
filename = "hello.txt"
fname = "hello.txt"

@pytest.fixture(autouse=True)
def setup(self, class_tmpdir):
with open(class_tmpdir / self.filename, "w") as file:
with open(class_tmpdir / self.fname, "w") as file:
file.write("hello, class-scoped tmpdir")

def test_class_scoped_tmpdir(self, class_tmpdir):
assert isinstance(class_tmpdir, Path)
assert class_tmpdir.is_dir()
assert self.__class__.__name__ in class_tmpdir.stem
assert Path(class_tmpdir / self.filename).is_file()
assert Path(class_tmpdir / self.fname).is_file()


def test_module_scoped_tmpdir(module_tmpdir):
Expand All @@ -74,38 +74,38 @@ def test_session_scoped_tmpdir(session_tmpdir):

# test CLI arguments --keep (-K) and --keep-failed for temp dir fixtures

FILE_NAME = "hello.txt"
test_keep_fname = "hello.txt"


@pytest.mark.meta("test_keep")
def test_keep_function_scoped_tmpdir_inner(function_tmpdir):
with open(function_tmpdir / FILE_NAME, "w") as f:
with open(function_tmpdir / test_keep_fname, "w") as f:
f.write("hello, function-scoped tmpdir")


@pytest.mark.meta("test_keep")
class TestKeepClassScopedTmpdirInner:
def test_keep_class_scoped_tmpdir_inner(self, class_tmpdir):
with open(class_tmpdir / FILE_NAME, "w") as f:
with open(class_tmpdir / test_keep_fname, "w") as f:
f.write("hello, class-scoped tmpdir")


@pytest.mark.meta("test_keep")
def test_keep_module_scoped_tmpdir_inner(module_tmpdir):
with open(module_tmpdir / FILE_NAME, "w") as f:
with open(module_tmpdir / test_keep_fname, "w") as f:
f.write("hello, module-scoped tmpdir")


@pytest.mark.meta("test_keep")
def test_keep_session_scoped_tmpdir_inner(session_tmpdir):
with open(session_tmpdir / FILE_NAME, "w") as f:
with open(session_tmpdir / test_keep_fname, "w") as f:
f.write("hello, session-scoped tmpdir")


@pytest.mark.parametrize("arg", ["--keep", "-K"])
def test_keep_function_scoped_tmpdir(function_tmpdir, arg):
inner_fn = test_keep_function_scoped_tmpdir_inner.__name__
file_path = Path(function_tmpdir / f"{inner_fn}0" / FILE_NAME)
file_path = Path(function_tmpdir / f"{inner_fn}0" / test_keep_fname)
args = [
__file__,
"-v",
Expand Down Expand Up @@ -144,7 +144,9 @@ def test_keep_class_scoped_tmpdir(tmp_path, arg):
]
assert pytest.main(args) == ExitCode.OK
assert Path(
tmp_path / f"{TestKeepClassScopedTmpdirInner.__name__}0" / FILE_NAME
tmp_path
/ f"{TestKeepClassScopedTmpdirInner.__name__}0"
/ test_keep_fname
).is_file()


Expand All @@ -171,7 +173,7 @@ def test_keep_module_scoped_tmpdir(tmp_path, arg):

print(keep_path)
pprint(list(keep_path.glob("*")))
assert FILE_NAME in [f.name for f in keep_path.glob("*")]
assert test_keep_fname in [f.name for f in keep_path.glob("*")]


@pytest.mark.parametrize("arg", ["--keep", "-K"])
Expand All @@ -188,12 +190,14 @@ def test_keep_session_scoped_tmpdir(tmp_path, arg, request):
tmp_path,
]
assert pytest.main(args) == ExitCode.OK
assert Path(tmp_path / f"{request.session.name}0" / FILE_NAME).is_file()
assert Path(
tmp_path / f"{request.session.name}0" / test_keep_fname
).is_file()


@pytest.mark.meta("test_keep_failed")
def test_keep_failed_function_scoped_tmpdir_inner(function_tmpdir):
with open(function_tmpdir / FILE_NAME, "w") as f:
with open(function_tmpdir / test_keep_fname, "w") as f:
f.write("hello, function-scoped tmpdir")

assert False, "oh no"
Expand All @@ -207,7 +211,9 @@ def test_keep_failed_function_scoped_tmpdir(function_tmpdir, keep):
args += ["--keep-failed", function_tmpdir]
assert pytest.main(args) == ExitCode.TESTS_FAILED

kept_file = Path(function_tmpdir / f"{inner_fn}0" / FILE_NAME).is_file()
kept_file = Path(
function_tmpdir / f"{inner_fn}0" / test_keep_fname
).is_file()
assert kept_file if keep else not kept_file


Expand All @@ -234,7 +240,7 @@ def pytest_terminal_summary(self, terminalreporter):

def test_meta():
args = [
f"{__file__}",
__file__,
"-v",
"-s",
"-k",
Expand Down Expand Up @@ -273,3 +279,40 @@ def test_large_test_model(large_test_model):
assert isinstance(large_test_model, Path)
assert large_test_model.is_file()
assert large_test_model.name == "mfsim.nam"


# test pandas fixture

test_pandas_fname = "pandas.txt"


@pytest.mark.meta("test_pandas")
def test_pandas_inner(function_tmpdir, use_pandas):
with open(function_tmpdir / test_pandas_fname, "w") as f:
f.write(str(use_pandas))


@pytest.mark.parametrize("pandas", ["yes", "no", "random"])
@pytest.mark.parametrize("arg", ["--pandas", "-P"])
def test_pandas(pandas, arg, function_tmpdir):
inner_fn = test_pandas_inner.__name__
args = [
__file__,
"-v",
"-s",
"-k",
inner_fn,
arg,
pandas,
"--keep",
function_tmpdir,
"-M",
"test_pandas",
]
assert pytest.main(args) == ExitCode.OK
res = open(next(function_tmpdir.rglob(test_pandas_fname))).readlines()[0]
assert res
if pandas == "yes":
assert "True" in res
elif pandas == "no":
assert "False" in res

0 comments on commit a41caa7

Please sign in to comment.