Skip to content

Commit 7b8b1f4

Browse files
TST: Simplify brainvision overrides tests; add default-unchanged guard
Reduce 7 test functions / 18 scenarios down to 5 functions / 10 scenarios by collapsing the marker_fname split, dropping the absolute-path parametrize on data_fname, dropping the truncation-warn edge case, and trimming the validation parametrize. Add an explicit test_overrides_default_unchanged that asserts overrides=None and overrides={} produce identical (nchan, sfreq, ch_names, meas_date, annotation count) to the no-overrides call. Verified manually with warnings.simplefilter('error') that the default read path emits zero warnings.
1 parent 35d81d9 commit 7b8b1f4

1 file changed

Lines changed: 51 additions & 67 deletions

File tree

mne/io/brainvision/tests/test_brainvision.py

Lines changed: 51 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -701,102 +701,57 @@ def test_ignore_marker_types():
701701
assert_array_equal(raw.annotations.description, expected_descriptions)
702702

703703

704-
def _stage_bv_trio(tmp_path, *, vhdr="test.vhdr", eeg="test.eeg", vmrk="test.vmrk"):
705-
"""Stage the .vhdr/.eeg/.vmrk trio under tmp_path; pass None to skip a file."""
706-
for src, dest in ((vhdr_path, vhdr), (eeg_path, eeg), (vmrk_path, vmrk)):
707-
if dest is not None:
708-
shutil.copy(src, tmp_path / dest)
709-
return tmp_path / "test.vhdr"
710-
711-
712704
@pytest.mark.parametrize(
713705
"overrides, exc, match",
714706
[
715707
({"not_a_key": 1}, ValueError, "not present in valid override keys"),
716708
(["not", "a", "dict"], TypeError, "must be an instance of dict"),
717-
({"data_fname": 5}, TypeError, "data_fname.*path-like"),
718-
({"marker_fname": 42}, TypeError, "marker_fname.*path-like"),
719709
({"n_channels": 0}, ValueError, "n_channels.*must be"),
720-
({"sfreq": -1.0}, ValueError, "sfreq.*must be"),
721-
({"ch_names": [1, 2, 3]}, TypeError, "ch_names.*str"),
722710
({"ch_names": ["A", "A", "B"]}, ValueError, "must contain unique names"),
723711
({"ch_names": list("abcde")}, ValueError, "length 5 but the file declares"),
724712
({"units_fallback": 7}, TypeError, "units_fallback.*str"),
725713
],
726714
)
727715
def test_overrides_validation(overrides, exc, match):
728-
"""Bad inputs raise at call time (validation + late-bound length check)."""
716+
"""Bad inputs raise at call time."""
729717
with pytest.raises(exc, match=match):
730718
read_raw_brainvision(vhdr_path, overrides=overrides)
731719

732720

733-
def test_overrides_none_and_empty_are_noop():
734-
"""``overrides=None`` and ``overrides={}`` both keep stock behavior."""
721+
def test_overrides_default_unchanged():
722+
"""``overrides=None`` and ``overrides={}`` match the no-overrides read exactly."""
723+
baseline = read_raw_brainvision(vhdr_path)
735724
for ov in (None, {}):
736-
assert read_raw_brainvision(vhdr_path, overrides=ov).info["nchan"] == 32
725+
raw = read_raw_brainvision(vhdr_path, overrides=ov)
726+
assert raw.info["nchan"] == baseline.info["nchan"]
727+
assert raw.info["sfreq"] == baseline.info["sfreq"]
728+
assert raw.ch_names == baseline.ch_names
729+
assert raw.info["meas_date"] == baseline.info["meas_date"]
730+
assert len(raw.annotations) == len(baseline.annotations)
737731

738732

739733
def test_overrides_units_fallback(tmp_path):
740-
"""Without units_fallback, [Channel Infos] truncation raises; with it, recovers."""
741-
use_vhdr = _stage_bv_trio(tmp_path, vhdr=None)
742-
skip_chans = {b"Ch31=", b"Ch32="}
734+
"""Truncated [Channel Infos] raises by default; ``units_fallback`` recovers."""
735+
# Drop the last two channel rows from the .vhdr
736+
use_vhdr = tmp_path / "test.vhdr"
737+
shutil.copy(eeg_path, tmp_path / "test.eeg")
738+
shutil.copy(vmrk_path, tmp_path / "test.vmrk")
739+
skip = (b"Ch31=", b"Ch32=")
743740
with open(vhdr_path, "rb") as fin, open(use_vhdr, "wb") as fout:
744741
for line in fin:
745-
if not any(line.startswith(p) for p in skip_chans):
742+
if not line.startswith(skip):
746743
fout.write(line)
747744

748745
with pytest.raises(RuntimeError, match=r"Incomplete \[Channel Infos\]"):
749746
read_raw_brainvision(use_vhdr)
750-
751747
with pytest.warns(RuntimeWarning, match="units_fallback overridden"):
752748
raw = read_raw_brainvision(use_vhdr, overrides={"units_fallback": "µV"})
753-
assert raw.info["nchan"] == 32
754-
assert raw.ch_names[:2] + raw.ch_names[-2:] == ["FP1", "FP2", "Ch31", "Ch32"]
755-
assert raw._orig_units["Ch31"] == raw._orig_units["Ch32"] == "µV"
756-
assert raw[:][0].shape[0] == 32
757-
758-
759-
@pytest.mark.parametrize("absolute", [False, True])
760-
def test_overrides_data_fname(tmp_path, absolute):
761-
"""data_fname override redirects the binary lookup (relative + absolute)."""
762-
use_vhdr = _stage_bv_trio(tmp_path, eeg="renamed.eeg")
763-
with pytest.raises(FileNotFoundError):
764-
read_raw_brainvision(use_vhdr, preload=True)
765-
override = str(tmp_path / "renamed.eeg") if absolute else "renamed.eeg"
766-
kwargs = dict(overrides={"data_fname": override}, preload=True)
767-
with pytest.warns(RuntimeWarning, match="data_fname overridden"):
768-
raw = read_raw_brainvision(use_vhdr, **kwargs)
769-
assert raw.get_data().shape[0] == 32
770-
771-
772-
@pytest.mark.parametrize(
773-
"skip_vmrk, override, expect_annots",
774-
[
775-
(True, False, False), # marker_fname=False: skip entirely
776-
(False, "renamed.vmrk", True), # marker_fname=<path>: redirect
777-
],
778-
)
779-
def test_overrides_marker_fname(tmp_path, skip_vmrk, override, expect_annots):
780-
"""marker_fname accepts False (skip) or a path (redirect)."""
781-
vmrk_arg = None if skip_vmrk else "renamed.vmrk"
782-
use_vhdr = _stage_bv_trio(tmp_path, vmrk=vmrk_arg)
783-
with pytest.warns(RuntimeWarning, match="marker_fname overridden"):
784-
raw = read_raw_brainvision(use_vhdr, overrides={"marker_fname": override})
785-
assert (len(raw.annotations) > 0) is expect_annots
786-
if not expect_annots:
787-
assert raw.info["meas_date"] is None
749+
assert raw.ch_names[-2:] == ["Ch31", "Ch32"]
750+
assert raw._orig_units["Ch31"] == "µV"
788751

789752

790-
def test_overrides_n_channels_truncation_warns(tmp_path):
791-
"""n_channels below [Channel Infos] row count warns about dropped rows."""
792-
use_vhdr = _stage_bv_trio(tmp_path)
793-
with _record_warnings(), pytest.warns(RuntimeWarning, match="dropped 2 trailing"):
794-
raw = read_raw_brainvision(use_vhdr, overrides={"n_channels": 30})
795-
assert raw.info["nchan"] == 30
796-
797-
798-
def test_overrides_sfreq_and_ch_names():
799-
"""Override ``sfreq`` and ``ch_names`` on the canonical test file."""
753+
def test_overrides_apply_simple_keys():
754+
"""Simple overrides (no staging) emit a warning and take effect."""
800755
with pytest.warns(RuntimeWarning, match="sfreq overridden"):
801756
raw = read_raw_brainvision(vhdr_path, overrides={"sfreq": 250.0})
802757
assert raw.info["sfreq"] == 250.0
@@ -805,7 +760,36 @@ def test_overrides_sfreq_and_ch_names():
805760
with pytest.warns(RuntimeWarning, match="ch_names overridden"):
806761
raw = read_raw_brainvision(vhdr_path, overrides={"ch_names": new_names})
807762
assert raw.ch_names == new_names
808-
assert "E0" in raw._orig_units
763+
764+
765+
def test_overrides_file_paths(tmp_path):
766+
"""``data_fname`` and ``marker_fname`` redirect the sibling file lookups."""
767+
shutil.copy(vhdr_path, tmp_path / "test.vhdr")
768+
shutil.copy(eeg_path, tmp_path / "renamed.eeg")
769+
shutil.copy(vmrk_path, tmp_path / "renamed.vmrk")
770+
use_vhdr = tmp_path / "test.vhdr"
771+
772+
overrides = {"data_fname": "renamed.eeg", "marker_fname": "renamed.vmrk"}
773+
with (
774+
_record_warnings(),
775+
pytest.warns(RuntimeWarning, match="data_fname overridden"),
776+
):
777+
raw = read_raw_brainvision(use_vhdr, overrides=overrides, preload=True)
778+
assert raw.get_data().shape[0] == 32
779+
assert len(raw.annotations) > 0
780+
781+
# marker_fname=False skips annotation reading entirely
782+
(tmp_path / "renamed.vmrk").unlink()
783+
with (
784+
_record_warnings(),
785+
pytest.warns(RuntimeWarning, match="marker_fname overridden"),
786+
):
787+
raw = read_raw_brainvision(
788+
use_vhdr,
789+
overrides={"data_fname": "renamed.eeg", "marker_fname": False},
790+
)
791+
assert len(raw.annotations) == 0
792+
assert raw.info["meas_date"] is None
809793

810794

811795
@testing.requires_testing_data

0 commit comments

Comments
 (0)