Skip to content

Architectural Redesign: Context Managers, SQL Snapshots, and Multi-Dialect E2E#3

Merged
fmartins merged 35 commits intomainfrom
fcm/feat/improve-dev-experience
Apr 4, 2026
Merged

Architectural Redesign: Context Managers, SQL Snapshots, and Multi-Dialect E2E#3
fmartins merged 35 commits intomainfrom
fcm/feat/improve-dev-experience

Conversation

@fmartins
Copy link
Copy Markdown
Owner

@fmartins fmartins commented Apr 4, 2026

Architectural Redesign: Context Managers, SQL Snapshots, and Multi-Dialect E2E

Overview

This PR represents a massive leap forward for pytest-capquery, completely overhauling the core architecture to be significantly more Pythonic, robust, and aligned with standard pytest philosophies.

A huge and sincere thank you to the community—especially @RonnyPfannschmidt from our recent GitHub discussions. Your candid feedback and pushback regarding global state leakage and AI query generation directly inspired the context-manager redesign and the new snapshotting capabilities. This tool is infinitely better because of that dialogue!

Key Changes

1. Context-Manager Based Isolation

  • Removed Global State: Completely removed the dangerous and leaky capquery.statements.clear() global state anti-pattern.
  • Localized Capture: Introduced the capquery.capture() context manager to securely isolate and assert queries against a specific, localized block of code.
  • Loose Assertions: Added support for capquery.capture(expected_count=X) to enforce strict query limits without hardcoding explicit SQL strings, protecting against N+1 regressions seamlessly.

2. Automated SQL Snapshots

  • Snapshot Manager: Implemented physical .sql snapshot generation and assertion via the new SnapshotManager.
  • CLI Integration: Added the --capquery-update CLI flag to automatically write and update expected query timelines directly to disk in a __capquery_snapshots__ directory.
  • Documentation as Code: Transitioned the recommended documentation workflow to favor physical snapshots over verbose inline SQL strings, dramatically improving test readability.

3. Comprehensive Multi-Dialect E2E Testing

  • Test Suite Split: Reorganized the test suite into dedicated unit and e2e execution paths.
  • Production Parity: Provisioned full Dockerized MySQL and PostgreSQL integration engines to ensure exact dialect parameter matching and accurate query tracking in production-like environments.

4. Developer Experience & Tooling

  • TDD Watcher: Introduced a Test-Driven Development watcher accessible via make tdd using pytest-watcher to continuously monitor database interactions during development.
  • Strict Formatting: Integrated ruff and docformatter into the pipeline for rigorous, automated code styling.

Checklist

  • All new and existing tests pass locally (make test).
  • Code is properly formatted and linted (make format and make check-format).
  • README.md has been fully updated to reflect the new snapshot-first workflow and context managers.
  • Tested against SQLite, MySQL, and PostgreSQL environments.

Thank you again to everyone who provided the critical feedback necessary to get this right. I would genuinely appreciate any further constructive suggestions or thoughts on this new context-manager approach!

fmartins added 3 commits April 3, 2026 23:17
- Implemented `QueryAsserter._fail_with_instructions` to output a perfectly formatted `assert_executed_queries` Python block directly to `sys.stdout` upon test failure.
- Bypassed Pytest's `E ` exception prefixing, allowing developers to instantly copy-paste updated query timelines without manual cleanup.
- Expanded test coverage in `test_assertion_failures.py` using `capsys` to rigorously validate the new stdout code generation formatting.
- Added comprehensive unit tests in `test_query_formatting.py` to cover `_normalize_params` (dict sorting, list conversion, scalar passthrough) and the `reformat_query` happy path.
- Cleaned up plugin docstrings to minimize diff noise.
@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Apr 4, 2026

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ All tests successful. No failed tests found.

📢 Thoughts on this report? Let us know!

fmartins added 26 commits April 4, 2026 00:52
- Added `pytest-watcher` to dependencies in `pyproject.toml`.
- Introduced a new `tdd` target in the Makefile for running tests in watch mode.
… for snapshot-based query validation"

This reverts commit 185dc24.
- Added alias support in `capquery.capture` for labeling distinct phases.
- Implemented multi-phase timeline serialization/deserialization for snapshots.
- Enhanced test examples with alias demonstrations and phase separation.
…otManager`

- Standardized query capturing and snapshot validation with `CapQueryWrapper`.
- Replaced legacy `capquery` references in unit tests.
- Enhanced test reliability by resetting session state with `db_session.rollback()`.
…gle class

- Unified `TxEvent` and `NormalizedStringStmt` into a single class to streamline usage.
- Updated imports and adapted unit tests to reflect the replacement.
- Simplified and standardized test cases for better readability and maintenance.
…ate files

- Extracted `QueryAsserter`, `CaptureContext`, `SnapshotManager`, and other classes into dedicated modules.
- Added `formatter.py` for SQL formatting utilities (`reformat_query`, `normalize_params`).
- Refactored unit tests to use new import paths.
- Removed duplicated logic and organized code for better maintainability.
- Removed `pytest-watcher` from main dependencies.
- Adjusted optional `test` dependencies for better clarity and grouping.
- Deleted legacy test files across unit, e2e, and integration layers.
- Cleaned up references to obsolete classes and methods in related tests.
- Deleted legacy test files across unit, e2e, and integration layers.
- Cleaned up references to obsolete classes and methods in related tests.
- Updated test functions and related logic to use `sqlite_session` instead of `db_session` for consistency.
- Removed the `db_session` fixture and cleaned up redundant code in `conftest.py`.
- Adjusted test imports and assertions accordingly.
- Updated test functions and related logic to use `sqlite_session` instead of `db_session` for consistency.
- Removed the `db_session` fixture and cleaned up redundant code in `conftest.py`.
- Adjusted test imports and assertions accordingly.
- Added detailed docstrings to clarify method arguments, return types, and behavior across `pytest_capquery` components.
- Replaced generic `Any` type hints with more specific `object` and custom types for consistency.
- Updated tests and example usages to reflect newly introduced type changes.
- Moved `pytest.register_assert_rewrite` call earlier in `conftest.py` for consistency.
- Improved resource cleanup in `plugin.py` by safely closing database connections and cursor objects.
- Removed redundant engine invalidation logic in test cleanup setup.
- Adjusted `ptw` command to simplify paths and prioritize `.venv` runner consistency during TDD.
- Introduced new tests to ensure `assert_matches_snapshot` handles missing managers and phase mismatches correctly.
- Added resource cleanup validation in `CapQueryWrapper.__exit__` to confirm proper closure of connections and cursors.
- Verified snapshot (de)serialization ignores empty queries.
- Unified all multi-line docstrings across test files into single-line format for better conciseness.
- Adjusted trailing commas in parameterized query assertions to improve readability.
- Standardized section headers and reduced redundant comments in unit, e2e, and plugin test cases.
- Separated shared `conftest.py` into `mysql/conftest.py` and `postgres/conftest.py` under `tests/e2e`.
- Improved test organization by isolating MySQL and PostgreSQL fixtures for better maintainability.
- Separated shared `conftest.py` into `mysql/conftest.py` and `postgres/conftest.py` under `tests/e2e`.
- Improved test organization by isolating MySQL and PostgreSQL fixtures for better maintainability.
…mples

- Updated feature descriptions to emphasize SQL snapshot documentation and N+1 query prevention.
- Refined quick start guide to highlight snapshot usage and manual assertion workflows.
- Added Makefile reference section for clarity on development commands.
- Improved contribution guidelines with streamlined steps and TDD workflow instructions.
@fmartins fmartins changed the title Fcm/feat/improve dev experience Architectural Redesign: Context Managers, SQL Snapshots, and Multi-Dialect E2E Apr 4, 2026
fmartins added 5 commits April 4, 2026 16:56
… captures

- Added unit tests to validate SQL snapshot generation and assertion for standard business logic.
- Introduced multi-phase tests to ensure proper snapshot serialization across distinct phases.
- Verified snapshot replacement behavior in update mode and error handling for missing snapshots.
- Added garbage collection to SQLite session fixture teardown to address intermittent ResourceWarnings.
- Ensured proper cleanup of ORM objects tied to the session before scope teardown.
…e, and resource cleanup validations

- Added tests for capture block isolation and sequential capture boundaries.
- Introduced validations for expected query count, bypass on exceptions, and active state assertions.
- Verified proper handling of resource cleanup and empty query serialization/deserialization in wrapper workflows.
…tures

- Deleted outdated unit tests for SQL snapshot generation and multi-phase assertions.
- Streamlined test suite by removing redundant snapshots and legacy serialization logic validation.
@fmartins fmartins marked this pull request as ready for review April 4, 2026 20:21
@fmartins fmartins merged commit 1313ac7 into main Apr 4, 2026
1 check passed
@fmartins fmartins deleted the fcm/feat/improve-dev-experience branch April 4, 2026 20:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants