3
3
import io
4
4
import json
5
5
from pathlib import Path
6
- from typing import Generator , List , Literal , cast
6
+ from typing import Dict , Generator , List , Literal , cast
7
7
8
8
import pytest
9
9
import rich
@@ -226,17 +226,40 @@ def timing_data(
226
226
yield timing_data
227
227
228
228
229
- TestCase = TestCaseIndexFile | TestCaseStream
229
+ class FixturesDict (Dict [Path , Fixtures ]):
230
+ """
231
+ A dictionary caches loaded fixture files to avoid reloading the same file
232
+ multiple times.
233
+ """
234
+
235
+ def __init__ (self ) -> None :
236
+ """Initialize the dictionary that caches loaded fixture files."""
237
+ self ._fixtures : Dict [Path , Fixtures ] = {}
238
+
239
+ def __getitem__ (self , key : Path ) -> Fixtures :
240
+ """Return the fixtures from the index file, if not found, load from disk."""
241
+ assert key .is_file (), f"Expected a file path, got '{ key } '"
242
+ if key not in self ._fixtures :
243
+ self ._fixtures [key ] = Fixtures .model_validate_json (key .read_text ())
244
+ return self ._fixtures [key ]
245
+
246
+
247
+ @pytest .fixture (scope = "session" )
248
+ def fixture_file_loader () -> Dict [Path , Fixtures ]:
249
+ """Return a singleton dictionary that caches loaded fixture files used in all tests."""
250
+ return FixturesDict ()
230
251
231
252
232
253
@pytest .fixture (scope = "function" )
233
254
def fixture (
234
- fixture_format : FixtureFormat ,
235
255
fixtures_source : FixturesSource ,
236
- test_case : TestCase ,
256
+ fixture_format : FixtureFormat ,
257
+ fixture_file_loader : Dict [Path , Fixtures ],
258
+ test_case : TestCaseIndexFile | TestCaseStream ,
237
259
) -> BaseFixture :
238
260
"""
239
- Create the blockchain engine fixture pydantic model for the current test case.
261
+ Load the fixture from a file or from stream in any of the supported
262
+ fixture formats.
240
263
241
264
The fixture is either already available within the test case (if consume
242
265
is taking input on stdin) or loaded from the fixture json file if taking
@@ -248,10 +271,8 @@ def fixture(
248
271
fixture = test_case .fixture
249
272
else :
250
273
assert isinstance (test_case , TestCaseIndexFile ), "Expected an index file test case"
251
- # TODO: Optimize, json files will be loaded multiple times. This pytest fixture
252
- # is executed per test case, and a fixture json will contain multiple test cases.
253
274
fixtures_file_path = Path (fixtures_source ) / test_case .json_path
254
- fixtures : Fixtures = Fixtures . model_validate_json ( fixtures_file_path . read_text ())
275
+ fixtures : Fixtures = fixture_file_loader [ fixtures_file_path ]
255
276
fixture = fixtures [test_case .id ]
256
277
assert isinstance (fixture , fixture_format ), (
257
278
f"Expected a { fixture_format .__name__ } test fixture"
0 commit comments