Skip to content
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
66 changes: 14 additions & 52 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,8 @@

test_data_path = Path(__file__).parent.absolute() / "test_data"

# A list to register functions that return general spools or patches
# These are to be used for running many patches/spools through
# Generic tests.
SPOOL_FIXTURES = []
# A list to register functions that return patches, for running many of
# them through generic tests (the `patch` meta-fixture below).
PATCH_FIXTURES = []

# By default DASCore only issues a warning once per line. This ensures
Expand Down Expand Up @@ -511,7 +509,7 @@ def patch(request):
return request.getfixturevalue(request.param)


@pytest.fixture(scope="class")
@pytest.fixture(scope="session")
def one_file_dir(tmp_path_factory, random_patch):
"""Create a directory with a single DAS file."""
out = Path(tmp_path_factory.mktemp("one_file_file_spool"))
Expand All @@ -526,7 +524,7 @@ def random_directory_spool(tmp_path_factory):
return dc.examples.random_directory_spool(path=path)


@pytest.fixture(scope="class")
@pytest.fixture(scope="session")
def two_patch_directory(tmp_path_factory, terra15_das_example_path, random_patch):
"""Create a directory of DAS files for testing."""
# first copy in a terra15 file
Expand All @@ -537,7 +535,7 @@ def two_patch_directory(tmp_path_factory, terra15_das_example_path, random_patch
return dir_path


@pytest.fixture(scope="class")
@pytest.fixture(scope="session")
def diverse_spool_directory(diverse_spool, tmp_path_factory):
"""Save the diverse spool contents to a directory.

Expand All @@ -549,45 +547,24 @@ def diverse_spool_directory(diverse_spool, tmp_path_factory):
return ex.spool_to_directory(diverse_spool, path=out)


@pytest.fixture(scope="class")
def adjacent_spool_directory(tmp_path_factory, adjacent_spool_no_overlap):
"""Create a directory of adjacent patches."""
# create a directory with several patch files in it.
dir_path = Path(tmp_path_factory.mktemp("data"))
for num, patch in enumerate(adjacent_spool_no_overlap):
path = dir_path / f"{num}_patch.hdf5"
dc.write(patch, path, file_format="dasdae")
return dir_path


# --- Spool fixtures


@pytest.fixture()
@register_func(SPOOL_FIXTURES)
def terra15_das_spool(terra15_das_example_path) -> SpoolType:
"""Return the spool of Terra15 Das Array."""
return read(terra15_das_example_path, file_format="terra15")


@pytest.fixture(scope="session")
@register_func(SPOOL_FIXTURES)
def terra15_das_unfinished_path() -> Path:
"""Return the spool of Terra15 Das Array."""
out = fetch("terra15_das_unfinished.hdf5")
assert out.exists()
return out


@pytest.fixture(scope="class")
@register_func(SPOOL_FIXTURES)
@pytest.fixture(scope="session")
def random_spool() -> SpoolType:
"""Init a random array."""
return get_example_spool("random_das")


@pytest.fixture(scope="class")
@register_func(SPOOL_FIXTURES)
@pytest.fixture(scope="session")
def adjacent_spool_no_overlap(random_patch) -> dc.BaseSpool:
"""
Create a spool with several patches within one time sample but not
Expand All @@ -609,22 +586,19 @@ def adjacent_spool_no_overlap(random_patch) -> dc.BaseSpool:
return dc.spool([pa2, pa1, pa3])


@pytest.fixture(scope="class")
@register_func(SPOOL_FIXTURES)
@pytest.fixture(scope="session")
def one_file_directory_spool(one_file_dir):
"""Create a directory with a single DAS file."""
return Spool.from_directory(one_file_dir).update()


@pytest.fixture(scope="class")
@register_func(SPOOL_FIXTURES)
@pytest.fixture(scope="session")
def diverse_spool():
"""Create a spool with a diverse set of patches for testing."""
return ex.diverse_spool()


@pytest.fixture(scope="class")
@register_func(SPOOL_FIXTURES)
@pytest.fixture(scope="session")
def diverse_directory_spool(diverse_spool_directory):
"""Save the diverse spool contents to a directory."""
out = dc.spool(diverse_spool_directory).update()
Expand All @@ -633,8 +607,7 @@ def diverse_directory_spool(diverse_spool_directory):
out.indexer.close()


@pytest.fixture(scope="class")
@register_func(SPOOL_FIXTURES)
@pytest.fixture(scope="session")
def basic_file_spool(two_patch_directory):
"""Return a DAS bank on basic_bank_directory."""
out = Spool.from_directory(two_patch_directory).update().update()
Expand All @@ -643,14 +616,12 @@ def basic_file_spool(two_patch_directory):


@pytest.fixture(scope="class")
@register_func(SPOOL_FIXTURES)
def terra15_file_spool(terra15_v5_path):
"""A file spool for terra15."""
return dc.spool(terra15_v5_path)


@pytest.fixture(scope="class")
@register_func(SPOOL_FIXTURES)
@pytest.fixture(scope="session")
def memory_spool_dim_1_patches():
"""
Memory spool with patches that have length 1 in one dimension.
Expand All @@ -666,8 +637,7 @@ def memory_spool_dim_1_patches():
return spool


@pytest.fixture(scope="class")
@register_func(SPOOL_FIXTURES)
@pytest.fixture(scope="session")
def all_examples_spool(tmp_path_factory, terra15_das_example_path):
"""Create a spool from all the example files."""
# Indexing the example files where they sit would write an index into the
Expand All @@ -683,8 +653,7 @@ def all_examples_spool(tmp_path_factory, terra15_das_example_path):
return dc.spool(directory).update()


@pytest.fixture(scope="class")
@register_func(SPOOL_FIXTURES)
@pytest.fixture(scope="session")
def memory_spool_small_dt_differences(random_spool):
"""Create a memory spool with slightly different time_steps."""
out = []
Expand All @@ -698,20 +667,13 @@ def memory_spool_small_dt_differences(random_spool):


@pytest.fixture(scope="session")
@register_func(SPOOL_FIXTURES)
def spool_with_non_coords():
"""Return a spool which has some non-coordinate patches inside."""
patches = list(dc.examples.get_example_spool(length=3))
patches += [x.mean("time") for x in patches]
return dc.spool(patches)


@pytest.fixture(scope="class", params=SPOOL_FIXTURES)
def spool(request):
"""A meta-fixtures for collecting all spools used in testing."""
return request.getfixturevalue(request.param)


# --- Misc. test fixtures


Expand Down
12 changes: 6 additions & 6 deletions tests/test_core/test_annotation_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def _denies_access() -> bool:
DENIES_ACCESS = _denies_access()


@pytest.fixture
@pytest.fixture(scope="module")
def curve() -> Moveout:
"""A moveout a path may be drawn from."""
return Moveout(
Expand All @@ -75,7 +75,7 @@ def curve() -> Moveout:
)


@pytest.fixture
@pytest.fixture(scope="module")
def regions() -> dc.AnnotationSet:
"""A set of regions, which a bare table can hold."""
frame = pd.DataFrame(
Expand Down Expand Up @@ -103,7 +103,7 @@ def regions() -> dc.AnnotationSet:
)


@pytest.fixture
@pytest.fixture(scope="module")
def with_vertices(curve) -> dc.AnnotationSet:
"""A set holding a hand-drawn path and one drawn from a curve."""
drawn = curve.vertices(5)
Expand Down Expand Up @@ -133,7 +133,7 @@ def with_vertices(curve) -> dc.AnnotationSet:
return dc.AnnotationSet(frame, dims=DIMS, vertices=vertices)


@pytest.fixture
@pytest.fixture(scope="module")
def picks() -> dc.AnnotationSet:
"""A set of time ranges made by a picker, on its own acquisition."""
frame = pd.DataFrame(
Expand Down Expand Up @@ -277,7 +277,7 @@ def test_an_unstated_bound(self, tmp_path):
class TestDeclaredDtypes:
"""A CSV states no types; the declaration beside it gives them back."""

@pytest.fixture
@pytest.fixture(scope="class")
def typed(self):
"""A set declaring a categorical and a nullable integer column."""
frame = pd.DataFrame(
Expand Down Expand Up @@ -1689,7 +1689,7 @@ def _forge(frame: pd.DataFrame, path, documents: str) -> None:
class TestParquet:
"""The same tables, with their types kept, for a set too big to want text."""

@pytest.fixture
@pytest.fixture(scope="class")
def mixed(self) -> dc.AnnotationSet:
"""A set whose columns hold what a CSV would have to spell as text."""
frame = pd.DataFrame(
Expand Down
18 changes: 3 additions & 15 deletions tests/test_core/test_coord_segmented.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,13 +133,6 @@ def test_fusing_inputs_rejected_by_class(self):
with pytest.raises(ValidationError, match="fuse"):
CoordSegmented(segments=(c1, c2))

def test_overlap_raises(self):
"""Overlapping segments are rejected."""
c1 = get_coord(start=0.0, stop=10.0, step=1.0)
c2 = get_coord(start=5.0, stop=15.0, step=1.0)
with pytest.raises(CoordError, match="overlap"):
concat_coords(c1, c2)

def test_shared_value_raises(self):
"""Segments sharing a boundary value are rejected (not strict)."""
c1 = get_coord(start=0.0, stop=10.0, step=1.0) # max 9
Expand Down Expand Up @@ -539,11 +532,6 @@ def test_the_guard_asks_every_segment(self, float_gap_coord):
class TestSimplifyAndSnap:
"""Tests for tolerance-bounded simplification and snapping."""

def test_simplify_zero_keeps_structure(self, float_gap_coord):
"""Zero tolerance cannot absorb a real gap."""
out = float_gap_coord.simplify(0)
assert out == float_gap_coord

def test_simplify_absorbs_gap_within_tolerance(self, float_gap_coord):
"""A large enough tolerance collapses to a single range."""
out = float_gap_coord.simplify(3.0)
Expand Down Expand Up @@ -1150,10 +1138,10 @@ def test_units(self):
class TestPlannedSpoolWriteGuard:
"""The gap write guard covers plan-assembled spools (round-4 F3)."""

@pytest.fixture()
def gapped_planned_spool(self, tmp_path):
@pytest.fixture(scope="class")
def gapped_planned_spool(self, tmp_path_factory):
"""A file-backed planned spool whose output spans a real gap."""
src = tmp_path / "src"
src = tmp_path_factory.mktemp("gapped_planned") / "src"
src.mkdir()
p1 = dc.get_example_patch()
t = p1.get_coord("time")
Expand Down
29 changes: 12 additions & 17 deletions tests/test_core/test_coords.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,11 +156,15 @@ def coord(request) -> BaseCoord:
return request.getfixturevalue(request.param)


@pytest.fixture(scope="session", params=COORDS)
@pytest.fixture(scope="session")
def long_coord(coord) -> BaseCoord:
"""Meta-fixture for returning all coords with len > 7."""
if len(coord) < 7:
pytest.skip("Only coords with len 3 or more used.")
"""The coord meta-fixture, for tests which need one longer than 7.

Every coord in COORDS is at least 100 long. Do not add `params=COORDS`
here: `coord` is already parametrized over them, so a second pass runs
each test once per pair of coords to see the same twelve.
"""
assert len(coord) > 7
return coord


Expand Down Expand Up @@ -195,10 +199,6 @@ def assert_value_in_one_step(coord, index, value, greater=True):
class TestBasics:
"""A suite of basic tests for coordinates."""

def test_coord_init(self, coord):
"""Simply run to insure all coords initialize."""
assert isinstance(coord, BaseCoord)

def test_bad_init(self):
"""Ensure no parameters raises error."""
with pytest.raises(CoordError):
Expand Down Expand Up @@ -1041,13 +1041,6 @@ def test_duplicate_array_samples(self, long_coord):
assert len(coord) == len(inds)
assert np.all(coord.values == coord.values[0])

def test_non_integer_array_with_samples_raises(self, evenly_sampled_coord):
"""Samples argument should require integer arrays."""
vals = np.array([1.01, 2.0, 3.0])
msg = "requires integer dtype"
with pytest.raises(CoordError, match=msg):
evenly_sampled_coord.select(vals, samples=True)

def test_duplicate_array_values(self, long_coord):
"""Ensure duplicate values cause duplicates in array."""
second_value = long_coord.values[1]
Expand Down Expand Up @@ -2020,7 +2013,7 @@ def test_timedelta(self, evenly_sampled_time_delta_coord):
out = evenly_sampled_time_delta_coord.get_sample_count(12 * dt)
assert out == 12

@pytest.mark.parametrize("sample", (0, 10, 100, 42, 13))
@pytest.mark.parametrize("sample", (0, 42))
def test_samples(self, evenly_sampled_coord, sample):
"""Ensure value is returned when samples==True."""
assert len(evenly_sampled_coord) >= sample
Expand Down Expand Up @@ -2351,7 +2344,9 @@ def test_negative_length_raises(
with pytest.raises(ParameterError, match="non-negative"):
coord.change_length(length)

@pytest.mark.parametrize("length", [2.5, 3.0, "3", None, True, False])
# A float, a string and a bool: the three kinds of thing which are not
# an integer length (bool is the one the check has a clause for).
@pytest.mark.parametrize("length", [2.5, "3", True])
def test_non_integer_length_raises(
self, evenly_sampled_coord, basic_non_coord, length
):
Expand Down
Loading
Loading