-
Notifications
You must be signed in to change notification settings - Fork 391
refactor(tests): Use pytest collection to load JSON fixtures #1666
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
d18197e to
8503878
Compare
| # Remove any python files in the downloaded files to avoid | ||
| # importing them. | ||
| for python_file in glob( | ||
| os.path.join(fixture_path, "**/*.py"), recursive=True | ||
| ): | ||
| try: | ||
| os.unlink(python_file) | ||
| except FileNotFoundError: | ||
| # Not breaking error, another process deleted it first | ||
| pass | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This feels... strange? I can't quite put my finger on why.
Like, why do the fixtures contain python files at all? Is there another way we could accomplish the same thing (like excluding a directory)?
I dunno, this just triggers my spidey sense 🤣
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the culprit: https://github.com/ethereum/legacytests/tree/1f581b8ccdc4c63acf5f2c5c1b155c690c32a8eb/src/LegacyTests/Cancun/GeneralStateTestsFiller/Pyspecs
Checking out ethereum/tests at this commit, when submodules are included, results in these python files being checked out too, and when collecting ./tests/json_infra/fixtures for JSON files, pytest tries to collect these files too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't we exclude that directory on the command line?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed that because with this approach the files are collected directly by pytest, as opposed to doing a glob in the test itself.
| ALL_FIXTURE_TYPES.append(BlockchainTestFixture) | ||
| ALL_FIXTURE_TYPES.append(StateTestFixture) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do these get executed when importing only, for example, .load_state_tests? From my limited knowledge of Python's import machinery, I would guess yes, but I'm just checking.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes that's correct, it gets executed only when importing from .helpers. If we were to, for example, import directly from .helpers.fixtures, this logic would not be executed and ALL_FIXTURE_TYPES would be empty, so it is indeed a bit brittle if being honest.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh really? I thought parent modules were implicitly imported. I'm glad I checked!
| big_memory: Tuple[Pattern[str], ...] | ||
|
|
||
|
|
||
| @lru_cache |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How often is this called to require an lru_cache? O.o
Depending on when the cache is populated (in worker vs. in master), using lru_cache can explode memory: each worker has its own cache.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed it thinking it might reduce the memory footprint and it did by half a GB, but it still consumes around 30GB+ because all fixtures are in memory when running.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* zkevm: add BLOBHASH benchs Signed-off-by: Ignacio Hagopian <[email protected]> * generalize params Signed-off-by: Ignacio Hagopian <[email protected]> * improvements Signed-off-by: Ignacio Hagopian <[email protected]> --------- Signed-off-by: Ignacio Hagopian <[email protected]>
|
I was thinking briefly about this. I also know next to nothing about pytest, so this might not make any sense at all, but... What if we use an LRU cache for the JSON files (one per worker), and loadgroup all the tests that come from the same file? So you'd read once during collection, find all the tests and group them by file, then while running the tests you minimize the number of times you need to re-read the same file. |
53e92c6 to
c6408c9
Compare
fix(tests): Don't cache fixtures Try to implement cache Fix caching feat(tests): Manage cache during execution
c6408c9 to
0110511
Compare
gurukamath
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even though this is a much larger re-factor than #1730, I do like this approach since it uses more of the pytest native patterns. So a one-time larger change might be worth it.
| ) | ||
|
|
||
| expected_post_state = load.json_to_state(json_data["postState"]) | ||
| assert chain.state == expected_post_state |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is currently not set up to catch any tests where the blocks themselves do not throw any exceptions but the overall state comparison fails . This I think is causing the current CI failure
* fix(tests): remove evm_tools marker from blockchain tests * remove coverage from json_infra * enhance(tools): add json_test_name to Hardfork * fix(tests): handle failing transactions in state tests * enhance(tests): add from and until fork option to json_infra * enhance(tests): run json_infra selectively * enhance(tests): subclass Hardfork * bug(tests): run all tests for t8n changes * enhance(tests): minor fix
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## forks/osaka #1666 +/- ##
===============================================
- Coverage 86.07% 85.90% -0.17%
===============================================
Files 743 743
Lines 44078 44076 -2
Branches 3894 3891 -3
===============================================
- Hits 37938 37865 -73
- Misses 5659 5722 +63
- Partials 481 489 +8
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
This commit refactors exception markers and marks the EEST static tests as slow
|
This PR is almost ready for review. However, I'm moving this to draft in order to resolve the discrepancy between the collectd vs run tests in CI for |
3e7826c to
5799559
Compare
SamWilsn
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Partial review so far
| # Get changed files and save to disk | ||
| FILE_LIST="changed_files.txt" | ||
| git diff --name-only "$BASE_SHA" "$HEAD_SHA" > "$FILE_LIST" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is BASH_SHA going to be the head of the base branch, or the merge-base of the two branches?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BASE_SHA in this case would be the head of the base branch
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, so a file added in the base branch would get tested here, even if no changes were made to it in this pull request?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The added file itself would not be tested but the addition might trigger a broader set of tests than what the PR explicitly changes. Perhaps this is not desirable and we should stick to comparing with the merge-base of the two branches. I'll give it a bit more thought
fb15e68 to
6a45550
Compare

🗒️ Description
This PR refactors the blockchain and state test infrastructure to leverage pytest's native collection mechanism via pytest_collect_file, eliminating redundant JSON file reads and improving test execution efficiency.
Key Improvements
Performance Impact
This refactoring significantly reduces I/O overhead for large test suites where the same JSON files contain multiple test cases across different forks.
Open Issues
Some failing tests still that need to be investigated, for now I'd like to start running this in CI and see how it improves execution speed.
🔗 Related Issues or PRs
N/A.
✅ Checklist
toxchecks to avoid unnecessary CI fails, see also Code Standards and Enabling Pre-commit Checks:uvx --with=tox-uv tox -e statictype(scope):.Cute Animal Picture