diff --git a/tests/data/archives/README.md b/tests/data/archives/README.md new file mode 100644 index 0000000..4ab1252 --- /dev/null +++ b/tests/data/archives/README.md @@ -0,0 +1,21 @@ +# Archives with legacy test data + +These archives should contain folders containing `.h5mu` test files +creasted with older `mudata` versions for regression testing. + +## Format + +A folder with the format `v` indicating the `mudata` version used +to create the file. + +Containing: +- `create_testfiles.py`: a script creating the testfiles. Should contain a + uv header specifying the critical dependencies. Can be run with `uv run create_testfile.py` + to create the testfile(s) +- `mudata.h5mu`: the created testfile. Needs to contain at minimum the data expected by + `test_io_backwards_compat.py`. + +## Automated tests + +The test `test_io_backwards_compat.py` will check each `mudata.h5mu` file in this folder if it can +be loaded correctly by the current `mudata` version. \ No newline at end of file diff --git a/tests/data/archives/v0.1.2/create_testfiles.py b/tests/data/archives/v0.1.2/create_testfiles.py new file mode 100644 index 0000000..6d73ea2 --- /dev/null +++ b/tests/data/archives/v0.1.2/create_testfiles.py @@ -0,0 +1,47 @@ +# /// script +# requires-python = ">=3.10" +# dependencies = [ +# "mudata==0.1.2", +# "numpy==1.*", # required as numpy 2 raises errors +# ] +# [tool.uv] +# exclude-newer = "2024-12-01T00:00:00Z" +# /// +import os + +import numpy as np +from anndata import AnnData + +from mudata import MuData + + +def create_mudata() -> MuData: + """Create a mudata testfile + + Returns: + MuData: MuData object with two AnnData objects + """ + return MuData( + { + "mod1": AnnData(np.arange(0, 100, 0.1).reshape(-1, 10)), + "mod2": AnnData(np.arange(101, 2101, 1).reshape(-1, 20)), + } + ) + + +def write_h5mu_testfile(mdata: MuData, filepath_h5mu: str | os.PathLike) -> None: + """Write a MuData object to a file + + Args: + mdata (MuData): MuData object to write + filepath_h5mu (str | os.PathLike): Path to write the MuData object + + Returns: + None + """ + mdata.write(filepath_h5mu) + + +if __name__ == "__main__": + mdata = create_mudata() + write_h5mu_testfile(mdata, "mudata.h5mu") diff --git a/tests/data/archives/v0.1.2/mudata.h5mu b/tests/data/archives/v0.1.2/mudata.h5mu new file mode 100644 index 0000000..adb9812 Binary files /dev/null and b/tests/data/archives/v0.1.2/mudata.h5mu differ diff --git a/tests/test_io_backwards_compat.py b/tests/test_io_backwards_compat.py new file mode 100644 index 0000000..8ae84ed --- /dev/null +++ b/tests/test_io_backwards_compat.py @@ -0,0 +1,35 @@ +from __future__ import annotations + +from pathlib import Path + +import numpy as np +import pytest +from anndata import AnnData +from anndata.tests.helpers import assert_equal + +from mudata import MuData, read_h5mu + +ARCHIVE_PTH = Path(__file__).parent / "data/archives" + + +@pytest.fixture(params=list(ARCHIVE_PTH.glob("v*")), ids=lambda x: x.name) +def archive_dir(request): + return request.param + + +@pytest.fixture +def mdata(): + return MuData( + { + "mod1": AnnData(np.arange(0, 100, 0.1).reshape(-1, 10)), + "mod2": AnnData(np.arange(101, 2101, 1).reshape(-1, 20)), + } + ) + + +class TestLegacyMuData: + def test_legacy_files(self, archive_dir, mdata): + from_h5mu = read_h5mu(archive_dir / "mudata.h5mu") + + for mod in mdata.mod: + assert_equal(from_h5mu.mod[mod].X, mdata.mod[mod].X, exact=False)