MAINT: Faster SQLite fixtures - #2640
Open
Roman Lutz (romanlutz) wants to merge 2 commits into
Open
Roman Lutz (romanlutz) wants to merge 2 commits into
Roman Lutz (romanlutz) wants to merge 2 commits into
Conversation
Migrate and validate a private SQLite template once per worker, then back up the schema into fresh per-test memory instances. Scope singleton and CentralMemory registration and keep cleanup owned by each fixture. Cover schema and row isolation, migration/reset behavior, thread access, and resource cleanup. Declare explicit memory fixtures for tests that relied on state left by earlier tests, and document the lifecycle. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Declare the existing CentralMemory fixture for the 18 optional target tests that relied on state leaked by the old SQLite fixture. Document all-extra validation for fixture changes. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
|
||
|
|
||
| Not all of our current tests follow these practices (we're working on it!) But for some good examples, see [test_tts_send_prompt_file_save_async](../../tests/unit/prompt_target/target/test_tts_target.py), which has many of these best practices incorporated in the test. | ||
|
|
Contributor
There was a problem hiding this comment.
should we also add something to the Unit Test Rules (.github/instructions/test.instructions.md)? like :
- Key memory fixtures from
tests/unit/conftest.py:- Use
patch_central_databasefor tests that accessCentralMemoryor construct targets, scorers, or attacks. Declare it explicitly even in constructor, validation, or identifier tests that do not directly query memory. - Use
sqlite_instancewhen the test needs to interact with the real isolated SQLite backend. - Do not rely on memory or singleton state left behind by another test. Each test must declare its own memory dependency.
- Use
- When changing shared memory fixtures, install all optional dependencies with
uv sync --extra alland runmake unit-test. Optional component tests must also exercise fixture isolation.
hannahwestra25
approved these changes
Sep 15, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Ordinary unit tests replayed the full Alembic migration history for every
sqlite_instance, adding substantial overhead across thousands of tests. Build and validate a pristine SQLite template once per pytest worker, then copy it with SQLite's backup API into a fresh database for each test.sqlite_instancefunction-scoped, with a new real SQLiteMemory instance, engine, results directory, and the existing threaded-session behavior. The template has its own engine and is query-only; it never becomes the shared singleton.reset_database()unchanged. Tests that exercise those paths still execute them. No workflow tracing settings, sharding, dependencies, or coverage thresholds change.Some constructor and identity tests now explicitly request
patch_central_databaseeven though their assertions do not query the database. Constructing a target callsCentralMemory.get_memory_instance()inPromptTarget.__init__; those tests previously relied on memory left behind by earlier tests. The added function/class markers remove that test-order dependency without introducing a global autouse fixture.Local measurements used Windows, Python 3.12.13, SQLite 3.50.4, and unchanged coverage 7.13.1 CTracer settings:
Fixture medians use 20 samples after two warmups and measure the complete setup. One-time template setup was measured separately at 272 ms without coverage and 786 ms with coverage per worker. These are local measurements, not an estimate of end-to-end CI savings.
Tests and Documentation
make unit-test-cov-xmlequivalent using the unchanged Makefile target: 17,107 passed, 124 skipped, 7 subtests passed; 91.96% line coverage, above the unchanged 78% gate. Run on Windows/Python 3.12 with the complete default locked dependencies, including feedgen.