Ensure that fixture objects are properly destroyed by the garbage collector at the end of their expected life-times (#2981).
(pytester: Pytester)
| 1139 | |
| 1140 | |
| 1141 | def test_fixture_values_leak(pytester: Pytester) -> None: |
| 1142 | """Ensure that fixture objects are properly destroyed by the garbage collector at the end of their expected |
| 1143 | life-times (#2981). |
| 1144 | """ |
| 1145 | pytester.makepyfile( |
| 1146 | """ |
| 1147 | import dataclasses |
| 1148 | import gc |
| 1149 | import pytest |
| 1150 | import weakref |
| 1151 | |
| 1152 | @dataclasses.dataclass |
| 1153 | class SomeObj: |
| 1154 | name: str |
| 1155 | |
| 1156 | fix_of_test1_ref = None |
| 1157 | session_ref = None |
| 1158 | |
| 1159 | @pytest.fixture(scope='session') |
| 1160 | def session_fix(): |
| 1161 | global session_ref |
| 1162 | obj = SomeObj(name='session-fixture') |
| 1163 | session_ref = weakref.ref(obj) |
| 1164 | return obj |
| 1165 | |
| 1166 | @pytest.fixture |
| 1167 | def fix(session_fix): |
| 1168 | global fix_of_test1_ref |
| 1169 | obj = SomeObj(name='local-fixture') |
| 1170 | fix_of_test1_ref = weakref.ref(obj) |
| 1171 | return obj |
| 1172 | |
| 1173 | def test1(fix): |
| 1174 | assert fix_of_test1_ref() is fix |
| 1175 | |
| 1176 | def test2(): |
| 1177 | gc.collect() |
| 1178 | # fixture "fix" created during test1 must have been destroyed by now |
| 1179 | assert fix_of_test1_ref() is None |
| 1180 | """ |
| 1181 | ) |
| 1182 | # Running on subprocess does not activate the HookRecorder |
| 1183 | # which holds itself a reference to objects in case of the |
| 1184 | # pytest_assert_reprcompare hook |
| 1185 | result = pytester.runpytest_subprocess() |
| 1186 | result.stdout.fnmatch_lines(["* 2 passed *"]) |
| 1187 | |
| 1188 | |
| 1189 | def test_fixture_order_respects_scope(pytester: Pytester) -> None: |
nothing calls this directly
no test coverage detected