SEP-1194: Implementation: Apply QA architecture to codebase - #830
SEP-1194: Implementation: Apply QA architecture to codebase#830cortiz-percona wants to merge 15 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR implements SEP’s approved QA/testing architecture by splitting the Python test suite into layered lanes (unit / integration / contract), centralizing reusable test factories/stubs, and wiring the new lanes into local tooling (Makefile) and CI (GitHub Actions). It primarily reorganizes and expands the test harness around the existing FastAPI multi-app layout (inventory, tasks, sep) so each lane can be run independently.
Changes:
- Introduces
tests/unit/,tests/integration/, andtests/contract/with per-lane auto-marking viaconftest.py, plus reference example tests for each lane. - Migrates existing tests/imports to the new structure (notably switching
tests.app.factories→tests.factories) and adds canonical external-service stubs undertests/_stubs/. - Adds Make targets (
test-unit,test-integration,test-contract) and updates CI to run these lanes separately; adds a reusable audit workflow and CI wiring.
Reviewed changes
Copilot reviewed 66 out of 262 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/unit/test_example_string_utils.py | Adds a reference unit-layer test covering pure string helpers. |
| tests/unit/conftest.py | Auto-applies the unit marker to tests under tests/unit/. |
| tests/unit/init.py | Marks the unit tests directory as a package (license header only). |
| tests/integration/test_example_api_route.py | Adds a reference integration test asserting each mounted app exposes openapi.json. |
| tests/integration/test_celery_signals.py | Adds integration tests for Celery correlation-ID/log-context signal helpers. |
| tests/integration/tasks/test_routes.py | Updates factories import path after test suite restructuring. |
| tests/integration/tasks/test_pmm_regression.py | Updates factories/import paths after restructuring. |
| tests/integration/tasks/test_models.py | Updates factories import path after restructuring. |
| tests/integration/tasks/test_deps.py | Updates factories import path after restructuring. |
| tests/integration/tasks/test_crud.py | Updates factories import path after restructuring. |
| tests/integration/tasks/test_config.py | Adds tests for app.tasks.config defaults/settings. |
| tests/integration/tasks/test_celery.py | Updates factories import path after restructuring. |
| tests/integration/tasks/periodic/test_routes.py | Updates factories import path after restructuring. |
| tests/integration/tasks/periodic/conftest.py | Adds periodic-task fixtures (SQLite + celery-beat tables + TestClient). |
| tests/integration/tasks/periodic/init.py | Marks periodic tests as a package (license header only). |
| tests/integration/tasks/execution/test_models.py | Updates factories import path after restructuring. |
| tests/integration/tasks/execution/test_exceptions.py | Adds tests for tasks execution exception types. |
| tests/integration/tasks/execution/executors/nomad/init.py | Marks Nomad executor test package (license header only). |
| tests/integration/tasks/execution/executors/celery/test_models.py | Updates factories import path after restructuring. |
| tests/integration/tasks/execution/executors/celery/init.py | Marks Celery executor test package (license header only). |
| tests/integration/tasks/execution/executors/init.py | Marks executors test package (license header only). |
| tests/integration/tasks/execution/init.py | Marks execution tests as a package (license header only). |
| tests/integration/tasks/db/test_engine.py | Adds tests for tasks DB engine/sessionmaker helper. |
| tests/integration/tasks/db/init.py | Marks tasks db tests as a package (license header only). |
| tests/integration/tasks/connectivity/test_service.py | Updates factories import path after restructuring. |
| tests/integration/tasks/connectivity/test_routes.py | Updates factories import path after restructuring. |
| tests/integration/tasks/connectivity/init.py | Marks connectivity tests as a package (license header only). |
| tests/integration/tasks/conftest.py | Updates factories import path after restructuring. |
| tests/integration/tasks/anonymizer/test_entities.py | Adds encode/decode round-trip test for anonymizer entity selection. |
| tests/integration/tasks/anonymizer/init.py | Marks anonymizer tests as a package (license header only). |
| tests/integration/tasks/init.py | Marks tasks integration tests as a package (license header only). |
| tests/integration/sep/utils/test_static.py | Adds tests for authenticated static-file serving behavior. |
| tests/integration/sep/utils/init.py | Marks sep utils tests as a package (license header only). |
| tests/integration/sep/test_scheduled_tasks_template.py | Adds template-render regression tests for scheduled tasks partial. |
| tests/integration/sep/test_main.py | Updates factories import path after restructuring. |
| tests/integration/sep/test_deps.py | Updates factories import path after restructuring. |
| tests/integration/sep/test_css_coverage.py | Adds guard test ensuring plugin CSS classes have sidebar icon rules. |
| tests/integration/sep/sync/test_models.py | Updates factories import path after restructuring. |
| tests/integration/sep/sync/test_exceptions.py | Adds tests for sync exception message/attribute behavior. |
| tests/integration/sep/sync/syncers/test_pmm.py | Updates factories import path after restructuring. |
| tests/integration/sep/sync/syncers/mysql/test_syncer.py | Updates factories import path after restructuring. |
| tests/integration/sep/sync/syncers/mysql/init.py | Marks mysql syncer tests as a package (license header only). |
| tests/integration/sep/sync/syncers/init.py | Marks syncers tests as a package (license header only). |
| tests/integration/sep/sync/conftest.py | Adds shared in-memory async DB session fixture for sync tests. |
| tests/integration/sep/sync/init.py | Marks sep sync tests as a package (license header only). |
| tests/integration/sep/snippets/test_forms.py | Adds tests for snippet HTML element models & description/info-icon rendering. |
| tests/integration/sep/snippets/test_crud.py | Adds CRUD tests for snippet manager get_or_create override behavior. |
| tests/integration/sep/snippets/models/init.py | Marks snippets models tests as a package (license header only). |
| tests/integration/sep/snippets/init.py | Marks snippets tests as a package (license header only). |
| tests/integration/sep/routes/test_stop_task.py | Updates factories import path after restructuring. |
| tests/integration/sep/routes/test_periodic_tasks.py | Updates factories import path after restructuring. |
| tests/integration/sep/routes/test_execution_events.py | Adds tests for SEP execution-events proxy route behavior. |
| tests/integration/sep/routes/test_download_files.py | Updates factories import path after restructuring. |
| tests/integration/sep/routes/conftest.py | Updates factories import path after restructuring. |
| tests/integration/sep/routes/init.py | Marks sep routes tests as a package (license header only). |
| tests/integration/sep/plugins/tasks/test_routes.py | Updates factories import path after restructuring. |
| tests/integration/sep/plugins/tasks/test_api_routes.py | Updates factories import path after restructuring. |
| tests/integration/sep/plugins/tasks/init.py | Marks tasks plugin tests as a package (license header only). |
| tests/integration/sep/plugins/snippets/init.py | Marks snippets plugin tests as a package (license header only). |
| tests/integration/sep/plugins/report/init.py | Marks report plugin tests as a package (license header only). |
| tests/integration/sep/plugins/mysql_backups/test_routes.py | Updates factories import path after restructuring. |
| tests/integration/sep/plugins/mysql_backups/restore/test_routes.py | Updates factories import path after restructuring. |
| tests/integration/sep/plugins/mysql_backups/restore/test_models.py | Adds validator/security-focused tests for restore backup_source input. |
| tests/integration/sep/plugins/mysql_backups/restore/init.py | Marks mysql_backups restore tests as a package (license header only). |
| tests/integration/sep/plugins/mysql_backups/init.py | Marks mysql_backups plugin tests as a package (license header only). |
| tests/integration/sep/plugins/inventory/test_sync.py | Updates factories import path after restructuring. |
| tests/integration/sep/plugins/inventory/test_schema.py | Adds tests for the inventory plugin schema object serialization/content. |
| tests/integration/sep/plugins/inventory/test_routes.py | Updates factories + conftest import paths after restructuring. |
| tests/integration/sep/plugins/inventory/test_api_routes.py | Updates in-doc references and conftest import paths after restructuring. |
| tests/integration/sep/plugins/inventory/init.py | Marks inventory plugin tests as a package (license header only). |
| tests/integration/sep/plugins/framework/test_deprecation.py | Adds tests for deprecated Jinja2 route class header/log behavior. |
| tests/integration/sep/plugins/framework/init.py | Marks framework plugin tests as a package (license header only). |
| tests/integration/sep/plugins/dipper/test_routes.py | Adds tests asserting dipper routes use deprecation route class contract. |
| tests/integration/sep/plugins/dipper/test_pcs_collect_pmm_mysql.py | Adds script-level tests for pcs-collect-pmm-mysql.py help/frontmatter invariants. |
| tests/integration/sep/plugins/dipper/test_deps.py | Updates factories import path after restructuring. |
| tests/integration/sep/plugins/dipper/conftest.py | Updates shared conftest import path after restructuring. |
| tests/integration/sep/plugins/dipper/init.py | Marks dipper plugin tests as a package (license header only). |
| tests/integration/sep/plugins/conftest.py | Updates factories import path after restructuring. |
| tests/integration/sep/plugins/checksums/test_schema.py | Adds tests for checksums plugin schema capability exposure. |
| tests/integration/sep/plugins/checksums/test_routes.py | Adds tests for checksums route behavior and dep-chain coverage. |
| tests/integration/sep/plugins/checksums/conftest.py | Updates shared conftest import path after restructuring. |
| tests/integration/sep/plugins/checksums/init.py | Marks checksums plugin tests as a package (license header only). |
| tests/integration/sep/plugins/backup_pg/test_routes.py | Updates factories import path after restructuring. |
| tests/integration/sep/plugins/backup_pg/conftest.py | Updates factories import path after restructuring. |
| tests/integration/sep/plugins/backup_pg/init.py | Marks backup_pg plugin tests as a package (license header only). |
| tests/integration/sep/plugins/backup_mongo/test_routes.py | Adds tests for backup_mongo route dep-chain and task fan-out behavior. |
| tests/integration/sep/plugins/backup_mongo/test_deps.py | Adds tests for backup_mongo dep payload construction & 404 swallowing behavior. |
| tests/integration/sep/plugins/backup_mongo/restore/test_routes.py | Adds tests for backup_mongo restore create/update dep-chain behavior. |
| tests/integration/sep/plugins/backup_mongo/restore/conftest.py | Adds fixtures for restore tests (RestoreCreate inputs). |
| tests/integration/sep/plugins/backup_mongo/restore/init.py | Marks backup_mongo restore tests as a package (license header only). |
| tests/integration/sep/plugins/backup_mongo/conftest.py | Updates factories import path after restructuring. |
| tests/integration/sep/plugins/backup_mongo/init.py | Marks backup_mongo plugin tests as a package (license header only). |
| tests/integration/sep/plugins/atw/init.py | Marks atw plugin tests as a package (license header only). |
| tests/integration/sep/plugins/archives/test_routes.py | Updates factories import path after restructuring. |
| tests/integration/sep/plugins/archives/test_deps.py | Updates factories import path after restructuring. |
| tests/integration/sep/plugins/archives/init.py | Marks archives plugin tests as a package (license header only). |
| tests/integration/sep/plugins/alters/test_routes.py | Updates factories import path after restructuring. |
| tests/integration/sep/plugins/alters/test_deps.py | Updates factories import path after restructuring. |
| tests/integration/sep/plugins/alters/init.py | Marks alters plugin tests as a package (license header only). |
| tests/integration/sep/plugins/alerts/test_crud.py | Adds CRUD tests for alerts backup persistence ordering/shape. |
| tests/integration/sep/plugins/alerts/test_config.py | Adds tests for alerts plugin PMM config factory/back-compat behavior. |
| tests/integration/sep/plugins/alerts/conftest.py | Adds in-memory session fixture for alerts plugin tests. |
| tests/integration/sep/plugins/alerts/init.py | Marks alerts plugin tests as a package (license header only). |
| tests/integration/sep/plugins/alert_troubleshooting/test_schema.py | Adds tests for alert_troubleshooting plugin schema + endpoint. |
| tests/integration/sep/plugins/alert_troubleshooting/conftest.py | Adds fixtures for alert_troubleshooting plugin tests (DB + snippets). |
| tests/integration/sep/plugins/alert_troubleshooting/init.py | Marks alert_troubleshooting tests as a package (license header only). |
| tests/integration/sep/plugins/init.py | Marks sep plugin tests as a package (license header only). |
| tests/integration/sep/migrations/init.py | Marks sep migrations tests package (license header only). |
| tests/integration/sep/middleware/init.py | Marks sep middleware tests package (license header only). |
| tests/integration/sep/db/init.py | Marks sep db tests package (license header only). |
| tests/integration/sep/conftest.py | Adds shared SEP integration fixtures (sessions, clients, RemoteAPI mocks). |
| tests/integration/sep/clients/init.py | Marks sep clients tests package (license header only). |
| tests/integration/sep/api/test_host_resolution.py | Adds tests for executor host resolution helpers. |
| tests/integration/sep/api/routes/test_task_stats.py | Adds tests for task-stats proxy route incl. 502 behavior + auth enforcement. |
| tests/integration/sep/api/routes/init.py | Marks sep api routes tests package (license header only). |
| tests/integration/sep/api/init.py | Marks sep api tests package (license header only). |
| tests/integration/sep/init.py | Marks sep integration tests as a package (license header only). |
| tests/integration/inventory/test_models.py | Adds tests for inventory model validators/enums. |
| tests/integration/inventory/test_main.py | Adds tests ensuring inventory lifespan is set at module import time. |
| tests/integration/inventory/test_config.py | Adds tests for inventory settings defaults. |
| tests/integration/inventory/routes/test_summary.py | Adds tests for inventory summary route response shape/counts. |
| tests/integration/inventory/routes/test_services.py | Updates factories import path after restructuring. |
| tests/integration/inventory/routes/test_schemas.py | Updates factories import path after restructuring. |
| tests/integration/inventory/routes/test_nodes.py | Updates factories import path after restructuring. |
| tests/integration/inventory/routes/init.py | Marks inventory routes tests package (license header only). |
| tests/integration/inventory/conftest.py | Updates factories import path after restructuring. |
| tests/integration/inventory/init.py | Marks inventory integration tests as a package (license header only). |
| tests/integration/core/utils/test_strings.py | Adds (migrated) tests for core string utils including slugify and b64 helpers. |
| tests/integration/core/utils/test_serialization.py | Adds (migrated) tests for JSON serialization helper behavior. |
| tests/integration/core/utils/test_imports.py | Adds (migrated) tests for dynamic import/validation helpers. |
| tests/integration/core/utils/test_fields.py | Adds (migrated) tests for core field validators/path resolution. |
| tests/integration/core/utils/test_dict.py | Adds (migrated) tests for dict utilities (sorting/filtering). |
| tests/integration/core/utils/test_date_time.py | Adds (migrated) tests for UTC datetime conversion helper. |
| tests/integration/core/utils/test_async_run.py | Adds (migrated) tests for async_run executor behavior. |
| tests/integration/core/utils/init.py | Marks core utils tests package (license header only). |
| tests/integration/core/test_security.py | Adds (migrated) tests for crypto serializers round-trip behavior. |
| tests/integration/core/test_models.py | Adds (migrated) tests for base model behaviors and pagination model validation. |
| tests/integration/core/test_log.py | Adds tests for contextual logging filter/context-var helpers. |
| tests/integration/core/test_exceptions.py | Adds tests for project HTTP exception helpers and details/headers behavior. |
| tests/integration/core/requests/test_correlation_id.py | Adds tests ensuring correlation ID is propagated in RemoteAPI requests. |
| tests/integration/core/requests/init.py | Marks core requests tests package (license header only). |
| tests/integration/core/middleware/init.py | Marks core middleware tests package (license header only). |
| tests/integration/core/db/test_sql_types.py | Adds tests for SQLAlchemy type decorators (AutoJSON, MaybeCompressedText). |
| tests/integration/core/db/test_config.py | Adds tests for DB options URL building and repr masking. |
| tests/integration/core/db/init.py | Marks core db tests package (license header only). |
| tests/integration/core/auth/providers/test_casdoor.py | Adds tests for CasdoorSDK repr masking and api-key encoding. |
| tests/integration/core/auth/providers/init.py | Marks auth providers tests package (license header only). |
| tests/integration/core/auth/init.py | Marks auth tests package (license header only). |
| tests/integration/core/alerts/test_config.py | Adds tests for alert provider configuration parsing/validation. |
| tests/integration/core/alerts/providers/test_pagerduty.py | Adds tests for PagerDuty provider payload and validation behaviors. |
| tests/integration/core/alerts/providers/init.py | Marks alerts providers tests package (license header only). |
| tests/integration/core/alerts/init.py | Marks core alerts tests package (license header only). |
| tests/integration/core/init.py | Marks core integration tests as a package (license header only). |
| tests/integration/conftest.py | Auto-applies the integration marker to tests under tests/integration/. |
| tests/integration/api/routes/test_users.py | Updates factories import path after restructuring. |
| tests/integration/api/routes/test_config.py | Adds tests for /api/config/alerts availability flag and auth behavior. |
| tests/integration/api/routes/init.py | Marks api routes tests package (license header only). |
| tests/integration/api/init.py | Marks api tests package (license header only). |
| tests/integration/init.py | Marks integration tests as a package (license header only). |
| tests/factories.py | Adds consolidated Polyfactory factories for test data generation. |
| tests/contract/test_example_openapi_contract.py | Adds reference Schemathesis-based contract test (skips if not installed). |
| tests/contract/conftest.py | Auto-applies the contract marker to tests under tests/contract/. |
| tests/contract/init.py | Marks contract tests as a package (license header only). |
| tests/conftest.py | Updates factories import path after restructuring. |
| tests/_stubs/pmm.py | Adds canonical PMM stub helpers for future consolidation. |
| tests/_stubs/nomad.py | Adds canonical Nomad stub helpers for future consolidation. |
| tests/_stubs/casdoor.py | Adds canonical Casdoor stub helpers for future consolidation. |
| tests/_stubs/init.py | Marks stubs directory as a package (license header only). |
| pyproject.toml | Registers new pytest markers (unit, integration, contract). |
| Makefile | Adds lane-specific test targets and updates .PHONY list. |
| .github/workflows/python.yaml | Splits CI test job into unit/integration lanes; adds contract lane job. |
| .github/workflows/ci.yml | Wires in reusable audit workflow and requires it for overall CI success. |
| .github/workflows/audit.yaml | Adds reusable workflow for pip-audit and pnpm audit. |
| .github/instructions/tests.instructions.md | Updates test layout/factory guidance to new directory structure. |
| .github/instructions/architecture.instructions.md | Updates test-path examples to new integration directory layout. |
|
@copilot resolve the merge conflicts in this pull request |
… CVE dependency fixes
Resolved. Merged |
|
@copilot resolve the merge conflicts in this pull request |
… PostgreSQL config files
Resolved (commit |
yyyyyyyan
left a comment
There was a problem hiding this comment.
I don't think this is the right approach. It's an enormous diff for something that could be done with simple pytest markers.
The rename of tests/app/ → tests/integration/ produced an enormous diff with no functional benefit. The auto-marker approach (pytest markers applied via conftest.py hooks) works regardless of the directory name, so the rename was pure churn. This commit: - Restores all test files to tests/app/ (original location) - Removes tests/integration/ directory - Adds pytest_collection_modifyitems to tests/app/conftest.py to auto-apply @pytest.mark.integration to all tests there - Keeps tests/unit/, tests/contract/, tests/_stubs/ unchanged
Fixed. Reverted the tests/app/ --> tests/integration/ rename and applied @pytest.mark.integration via pytest_collection_modifyitems in tests/app/conftest.py instead |
example, add QA docs - _stubs/pmm,nomad: point at real surfaces (PMMRemoteAPI.get_nodes/ get_services, NomadExecutor.dispatch_job); dispatch_job is sync so use MagicMock - contract conftest: filter by fspath so full-suite runs don't over-mark - instructions: revert tests/integration -> tests/app after the rename revert - restore tests/app/test_example_api_route.py (lost in the rename revert) - docs: add qa-architecture.md + testing-guidelines.md (AC3); signal the existing Vitest layer as canonical (AC2)
Replace the POSIX substring path guard ("tests/X/" in str(item.fspath)) in the unit/integration/contract auto-markers with a pathlib check (Path(__file__).parent in item.path.parents).
Local TestingRan the lanes and exercised the fixed stubs against real targets. Results:
Stub fixes — verified patching real surfacesThe canonical stubs previously pointed at non-existent paths (
Marker scopingConfirmed the Not run locally
|
|
Hi team, take a look when you have a moment. Want to make sure it doesn't stall. Happy to help it forward once there's feedback. |
Summary
Implements the approved QA architecture (SEP-1191) in the repository: a layered testing model selected by markers, canonical external-service stubs, reference examples per lane, and CI integration for each lane.
tests/unit/andtests/contract/alongside the existingtests/app/tree, plustests/_stubs/as the single source of truth for Casdoor / Nomad / PMM stubs. The lane markers (unit,integration,contract) are applied automatically by per-directoryconftest.pyviapytest_collection_modifyitems— no manual decoration required. Integration tests stay intests/app/(which mirrorsapp/one-to-one); the directory is not renamed — the marker is the layer.tests/unit/test_example_string_utils.py— pure logic, no I/Otests/app/test_example_api_route.py—TestClientagainst the mounted appstests/contract/test_example_openapi_contract.py— Schemathesis against a mounted app'sopenapi()(skips cleanly until the dependency lands — see below)frontend/packages/e2e/tests/example.spec.ts— Playwright + Vite preview + API mockingtests/_stubs/{casdoor,nomad,pmm}.pyexposepatch_*helpers that point at the real client surfaces (CasdoorSDK.introspect_token/get_user,NomadExecutor.dispatch_job,PMMRemoteAPI.get_nodes/get_services). Milestone M4 consolidates the per-plugin stubs here.make test-unit,make test-integration,make test-contract; splits the lanes into separate jobs in.github/workflows/python.yaml; adds.github/workflows/audit.yaml(reusablepip-audit+pnpm audit) wired intoci.yml..github/instructions/tests.instructions.mdand adds the operational playbook indocs/testing-guidelines.md+ the architecture indocs/qa-architecture.md.Tested
make test-unit— passesmake test-integration— passes (auto-integrationmarker applied totests/app/)make test-contract— runs and skips cleanly (schemathesis not installed; tolerated exit code 5)make lint(ruff + djlint)pnpm --filter @sep/e2e test:e2e—example.spec.tspasses against the Vite preview server with API mockingpython.yaml,audit.yaml) executed on the branchChecklist
make run-pre-commit)make makemigrations) — N/A (no model changes)changelog.d/— N/A (internal-only tooling/test change)