jpayne@68
|
1 """
|
jpayne@68
|
2 Pytest configuration and fixtures for the Numpy test suite.
|
jpayne@68
|
3 """
|
jpayne@68
|
4 import os
|
jpayne@68
|
5 import tempfile
|
jpayne@68
|
6
|
jpayne@68
|
7 import hypothesis
|
jpayne@68
|
8 import pytest
|
jpayne@68
|
9 import numpy
|
jpayne@68
|
10
|
jpayne@68
|
11 from numpy.core._multiarray_tests import get_fpu_mode
|
jpayne@68
|
12
|
jpayne@68
|
13
|
jpayne@68
|
14 _old_fpu_mode = None
|
jpayne@68
|
15 _collect_results = {}
|
jpayne@68
|
16
|
jpayne@68
|
17 # Use a known and persistent tmpdir for hypothesis' caches, which
|
jpayne@68
|
18 # can be automatically cleared by the OS or user.
|
jpayne@68
|
19 hypothesis.configuration.set_hypothesis_home_dir(
|
jpayne@68
|
20 os.path.join(tempfile.gettempdir(), ".hypothesis")
|
jpayne@68
|
21 )
|
jpayne@68
|
22
|
jpayne@68
|
23 # We register two custom profiles for Numpy - for details see
|
jpayne@68
|
24 # https://hypothesis.readthedocs.io/en/latest/settings.html
|
jpayne@68
|
25 # The first is designed for our own CI runs; the latter also
|
jpayne@68
|
26 # forces determinism and is designed for use via np.test()
|
jpayne@68
|
27 hypothesis.settings.register_profile(
|
jpayne@68
|
28 name="numpy-profile", deadline=None, print_blob=True,
|
jpayne@68
|
29 )
|
jpayne@68
|
30 hypothesis.settings.register_profile(
|
jpayne@68
|
31 name="np.test() profile",
|
jpayne@68
|
32 deadline=None, print_blob=True, database=None, derandomize=True,
|
jpayne@68
|
33 suppress_health_check=list(hypothesis.HealthCheck),
|
jpayne@68
|
34 )
|
jpayne@68
|
35 # Note that the default profile is chosen based on the presence
|
jpayne@68
|
36 # of pytest.ini, but can be overridden by passing the
|
jpayne@68
|
37 # --hypothesis-profile=NAME argument to pytest.
|
jpayne@68
|
38 _pytest_ini = os.path.join(os.path.dirname(__file__), "..", "pytest.ini")
|
jpayne@68
|
39 hypothesis.settings.load_profile(
|
jpayne@68
|
40 "numpy-profile" if os.path.isfile(_pytest_ini) else "np.test() profile"
|
jpayne@68
|
41 )
|
jpayne@68
|
42
|
jpayne@68
|
43
|
jpayne@68
|
44 def pytest_configure(config):
|
jpayne@68
|
45 config.addinivalue_line("markers",
|
jpayne@68
|
46 "valgrind_error: Tests that are known to error under valgrind.")
|
jpayne@68
|
47 config.addinivalue_line("markers",
|
jpayne@68
|
48 "leaks_references: Tests that are known to leak references.")
|
jpayne@68
|
49 config.addinivalue_line("markers",
|
jpayne@68
|
50 "slow: Tests that are very slow.")
|
jpayne@68
|
51 config.addinivalue_line("markers",
|
jpayne@68
|
52 "slow_pypy: Tests that are very slow on pypy.")
|
jpayne@68
|
53
|
jpayne@68
|
54
|
jpayne@68
|
55 def pytest_addoption(parser):
|
jpayne@68
|
56 parser.addoption("--available-memory", action="store", default=None,
|
jpayne@68
|
57 help=("Set amount of memory available for running the "
|
jpayne@68
|
58 "test suite. This can result to tests requiring "
|
jpayne@68
|
59 "especially large amounts of memory to be skipped. "
|
jpayne@68
|
60 "Equivalent to setting environment variable "
|
jpayne@68
|
61 "NPY_AVAILABLE_MEM. Default: determined"
|
jpayne@68
|
62 "automatically."))
|
jpayne@68
|
63
|
jpayne@68
|
64
|
jpayne@68
|
65 def pytest_sessionstart(session):
|
jpayne@68
|
66 available_mem = session.config.getoption('available_memory')
|
jpayne@68
|
67 if available_mem is not None:
|
jpayne@68
|
68 os.environ['NPY_AVAILABLE_MEM'] = available_mem
|
jpayne@68
|
69
|
jpayne@68
|
70
|
jpayne@68
|
71 #FIXME when yield tests are gone.
|
jpayne@68
|
72 @pytest.hookimpl()
|
jpayne@68
|
73 def pytest_itemcollected(item):
|
jpayne@68
|
74 """
|
jpayne@68
|
75 Check FPU precision mode was not changed during test collection.
|
jpayne@68
|
76
|
jpayne@68
|
77 The clumsy way we do it here is mainly necessary because numpy
|
jpayne@68
|
78 still uses yield tests, which can execute code at test collection
|
jpayne@68
|
79 time.
|
jpayne@68
|
80 """
|
jpayne@68
|
81 global _old_fpu_mode
|
jpayne@68
|
82
|
jpayne@68
|
83 mode = get_fpu_mode()
|
jpayne@68
|
84
|
jpayne@68
|
85 if _old_fpu_mode is None:
|
jpayne@68
|
86 _old_fpu_mode = mode
|
jpayne@68
|
87 elif mode != _old_fpu_mode:
|
jpayne@68
|
88 _collect_results[item] = (_old_fpu_mode, mode)
|
jpayne@68
|
89 _old_fpu_mode = mode
|
jpayne@68
|
90
|
jpayne@68
|
91
|
jpayne@68
|
92 @pytest.fixture(scope="function", autouse=True)
|
jpayne@68
|
93 def check_fpu_mode(request):
|
jpayne@68
|
94 """
|
jpayne@68
|
95 Check FPU precision mode was not changed during the test.
|
jpayne@68
|
96 """
|
jpayne@68
|
97 old_mode = get_fpu_mode()
|
jpayne@68
|
98 yield
|
jpayne@68
|
99 new_mode = get_fpu_mode()
|
jpayne@68
|
100
|
jpayne@68
|
101 if old_mode != new_mode:
|
jpayne@68
|
102 raise AssertionError("FPU precision mode changed from {0:#x} to {1:#x}"
|
jpayne@68
|
103 " during the test".format(old_mode, new_mode))
|
jpayne@68
|
104
|
jpayne@68
|
105 collect_result = _collect_results.get(request.node)
|
jpayne@68
|
106 if collect_result is not None:
|
jpayne@68
|
107 old_mode, new_mode = collect_result
|
jpayne@68
|
108 raise AssertionError("FPU precision mode changed from {0:#x} to {1:#x}"
|
jpayne@68
|
109 " when collecting the test".format(old_mode,
|
jpayne@68
|
110 new_mode))
|
jpayne@68
|
111
|
jpayne@68
|
112
|
jpayne@68
|
113 @pytest.fixture(autouse=True)
|
jpayne@68
|
114 def add_np(doctest_namespace):
|
jpayne@68
|
115 doctest_namespace['np'] = numpy
|
jpayne@68
|
116
|
jpayne@68
|
117 @pytest.fixture(autouse=True)
|
jpayne@68
|
118 def env_setup(monkeypatch):
|
jpayne@68
|
119 monkeypatch.setenv('PYTHONHASHSEED', '0')
|
jpayne@68
|
120
|
jpayne@68
|
121
|
jpayne@68
|
122 @pytest.fixture(params=[True, False])
|
jpayne@68
|
123 def weak_promotion(request):
|
jpayne@68
|
124 """
|
jpayne@68
|
125 Fixture to ensure "legacy" promotion state or change it to use the new
|
jpayne@68
|
126 weak promotion (plus warning). `old_promotion` should be used as a
|
jpayne@68
|
127 parameter in the function.
|
jpayne@68
|
128 """
|
jpayne@68
|
129 state = numpy._get_promotion_state()
|
jpayne@68
|
130 if request.param:
|
jpayne@68
|
131 numpy._set_promotion_state("weak_and_warn")
|
jpayne@68
|
132 else:
|
jpayne@68
|
133 numpy._set_promotion_state("legacy")
|
jpayne@68
|
134
|
jpayne@68
|
135 yield request.param
|
jpayne@68
|
136 numpy._set_promotion_state(state)
|