-
Notifications
You must be signed in to change notification settings - Fork 107
Expand file tree
/
Copy pathconftest.py
More file actions
152 lines (114 loc) · 5.12 KB
/
Copy pathconftest.py
File metadata and controls
152 lines (114 loc) · 5.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#!/usr/bin/env python3
import logging
import re
from pathlib import Path
import pytest
import yaml
import pyphi
log = logging.getLogger("pyphi.test")
collect_ignore = ["setup.py", ".pythonrc.py"]
# Also ignore everything that git ignores.
with open(Path(__file__).parent / ".gitignore") as f:
collect_ignore += list(filter(None, f.read().split("\n")))
# The MCP server package imports the optional ``mcp`` dependency at module
# level, so exclude it from doctest-module collection when that extra is absent.
try:
import mcp # noqa: F401
except ImportError:
collect_ignore.append("pyphi/mcp")
IIT_3_CONFIG = "pyphi_config_3.0.yml"
# Run slow tests separately with command-line option, filter tests
# ================================================================
def pytest_addoption(parser):
parser.addoption(
"--filter", action="store", help="only run tests with the given mark"
)
parser.addoption("--outdated", action="store_true", help="run outdated tests")
parser.addoption("--slow", action="store_true", help="run slow tests")
parser.addoption("--veryslow", action="store_true", help="run very slow tests")
def pytest_configure(config):
# ``-m slow`` alone selects slow-marked tests and then skips every one
# (the setup hook below requires ``--slow``), which reads as a green
# run. Fail loudly instead of silently skipping the whole selection.
markexpr = getattr(config.option, "markexpr", "") or ""
for mark, flag in (("slow", "--slow"), ("veryslow", "--veryslow")):
if re.search(rf"(?<!not )\b{mark}\b", markexpr) and not config.getoption(flag):
raise pytest.UsageError(
f"'-m {mark}' selects {mark}-marked tests, but they are "
f"skipped unless {flag} is also given; add {flag}"
)
def pytest_runtest_setup(item):
filt = item.config.getoption("--filter")
if filt:
if filt not in item.keywords:
pytest.skip(f"only running tests with the '{filt}' mark")
else:
if "outdated" in item.keywords and not item.config.getoption("--outdated"):
pytest.skip("need --outdated option to run")
if "slow" in item.keywords and not item.config.getoption("--slow"):
pytest.skip("need --slow option to run")
if "veryslow" in item.keywords and not item.config.getoption("--veryslow"):
pytest.skip("need --veryslow option to run")
# PyPhi configuration management
# ================================================================
@pytest.fixture(scope="function")
def restore_config_afterwards():
"""Reset PyPhi configuration after a test.
Useful for doctests that can't be decorated with `config.override`.
"""
with pyphi.config.override():
yield
@pytest.fixture(scope="session", autouse=True)
def disable_progress_bars():
"""Disable progress bars during tests.
Without this progress bars are already disabled for unit tests; doctests
work differently, I think because of output redirection.
"""
with pyphi.config.override(PROGRESS_BARS=False):
yield
@pytest.fixture(autouse=True)
def _restore_config_after_test():
"""Snapshot the global config before each test and restore after.
Defensive test hygiene against any test or doctest that mutates
``pyphi.config`` without unwinding (e.g. a raw assignment outside an
``override`` block). Lives at the root so it covers doctests collected
from ``pyphi/`` as well as tests under ``test/``.
"""
snapshot = pyphi.config.snapshot()
try:
yield
finally:
pyphi.config.install_snapshot(snapshot)
@pytest.fixture(scope="function")
def use_iit_3_config():
"""Use the IIT-3 configuration for all tests."""
with open(IIT_3_CONFIG) as f:
iit3_config = yaml.load(f, Loader=yaml.SafeLoader)
with pyphi.config.override(**iit3_config):
yield
# Cache management and fixtures
# ================================================================
@pytest.fixture(scope="function", autouse=True)
def flushcache(request): # noqa: ARG001
"""No-op cache flush between tests.
PyPhi's caches are designed to be safe to share across tests:
combinatorial caches in ``partition.py`` / ``distribution.py`` /
``combinatorics.py`` memoize pure functions (no per-test state to
pollute); the kernel ``_memoize`` keys on ``id(cs)`` and uses
``weakref.finalize`` to evict cache entries when a CandidateSystem
is garbage-collected; Network purview caches are anonymous and die
with their Network. Clearing them between every test forces
expensive re-enumeration of partitions on every fixture setup
(5x suite slowdown observed during P9 bisect).
"""
log.info("Flushing caches... (no-op)")
# Parallel (local backend)
# ================================================================
@pytest.fixture(scope="module")
def parallel_context():
"""Set up parallel computation context.
With the local backend, no special initialization is needed.
This fixture is kept for API compatibility with existing tests.
"""
# Local backend uses ProcessPoolExecutor which doesn't require init
yield None