Test Infrastructure Standards
Purpose: Comprehensive guide for test infrastructure standards and patterns in Atom.
Last Updated: 2026-03-23
Overview
This document outlines the test infrastructure standards for the Atom project, covering:
- Test fixtures and patterns
- Database isolation and test data management
- Failure artifact capture (screenshots, videos)
- Test reporting (Allure, HTML, JSON)
- Parallel execution patterns
- Test cleanup and teardown
Target Audience: Test engineers, developers writing tests, CI/CD engineers
Test Fixtures Standards
Fixture Scope
Session-scoped fixtures (expensive, shared):
@pytest.fixture(scope="session")
def browser():
"""Shared browser instance for all tests."""
# Use for: Browser launch, server startup
Function-scoped fixtures (default, isolated):
@pytest.fixture(scope="function")
def page(browser):
"""New page for each test."""
# Use for: Page objects, test data
Autouse fixtures (automatic):
@pytest.fixture(autouse=True)
def track_page_for_screenshots(request, page):
"""Track page for automatic screenshot capture."""
# Runs for every test automatically
Fixture Naming Conventions
- Descriptive names:
screenshot_page, notsp - Return type hints in docstrings
- Yield for cleanup, return for values
Database Isolation Patterns
Worker-Specific Database Isolation
All tests automatically get worker-specific database isolation via db_session fixture:
@pytest.fixture(scope="function")
def db_session():
"""
Worker-specific database session with automatic rollback.
Each pytest-xdist worker gets its own database file to prevent
test data collisions during parallel execution.
"""
# Worker ID: gw0, gw1, gw2, etc.
# Database: atom_test_<worker_id>.db
# Automatic rollback after each test
Key Benefits:
- No test data collisions between workers
- No cleanup code needed in tests
- Full parallel execution support
Usage:
def test_create_agent(db_session):
agent = AgentRegistry(id="test-agent", name="Test")
db_session.add(agent)
db_session.commit()
# Auto-rollback after test
Failure Artifacts (INFRA-04)
Automatic Capture
Failed E2E tests automatically capture:
- Screenshot: Full-page screenshot saved to
artifacts/screenshots/ - Video: Browser recording saved to
artifacts/videos/(CI only) - Allure Report: Artifacts attached to test result for easy viewing
Screenshot Format
- Filename:
{timestamp}_{test_name}.png - Full page capture (includes scrolled content)
- Available in:
artifacts/screenshots/
Example:
20260323_170120_test_login_success.png
Video Recording
- Enabled in CI only (GITHUB_ACTIONS=true)
- Format: WEBM
- Available in:
artifacts/videos/ - Accessed via:
page.video.path()
Example:
20260323_170120_test_login_success.webm
Allure Integration
@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
"""Attach screenshots/videos to Allure on failure."""
outcome = yield
rep = outcome.get_result()
if rep.when == "call" and rep.failed:
# Capture and attach artifacts
allure.attach.file(screenshot_path, ...)
allure.attach.file(video_path, ...)
Benefits:
- Artifacts embedded in test report
- One-click viewing in Allure UI
- No manual file searching
Viewing Artifacts
# Local: Check artifacts directory
ls artifacts/screenshots/
ls artifacts/videos/
# CI: Download from workflow run artifacts
# Allure: Open report and click failed test
allure open allure-report
Manual Screenshot Capture
def test_manual_screenshot(page):
page.screenshot(path="custom-screenshot.png")
# Attach to Allure
allure.attach.file(
"custom-screenshot.png",
name="Custom Screenshot",
attachment_type=allure.attachment_type.PNG
)
Test Cleanup Patterns
Automatic Cleanup
Use fixtures with yield for cleanup:
@pytest.fixture(scope="function")
def temp_file():
"""Create temp file and clean up after test."""
path = "/tmp/test-file.txt"
with open(path, "w") as f:
f.write("test data")
yield path
# Cleanup
os.remove(path)
Database Cleanup
Use transaction rollback (automatic):
def test_create_agent(db_session):
agent = AgentRegistry(id="test", name="Test")
db_session.add(agent)
db_session.commit()
# Auto-rollback after test
Resource Cleanup
@pytest.fixture(scope="function")
def server():
"""Start server and stop after test."""
srv = start_server(port=8000)
yield srv
srv.stop() # Cleanup
Test Reporting Standards
Allure Reporting
Generate Report:
pytest tests/ --alluredir=allure-results
allure generate allure-results --clean -o allure-report
allure open allure-report
Benefits:
- Rich test report with screenshots/videos
- Test history and trends
- Suites, categories, and tags
HTML Reporting
Generate Report:
pytest tests/ --html=report.html --self-contained-html
Features:
- Embedded screenshots in failed tests
- Test execution summary
- Test duration and logs
JSON Reporting
Generate Report:
pytest tests/ --json-report --json-report-file=report.json
Use Case: CI/CD pass rate parsing
Parallel Execution Standards
pytest-xdist Configuration
Run tests in parallel:
pytest -n auto # Auto-detect CPU count
pytest -n 4 # Use 4 workers
Worker Isolation:
- Each worker gets own database file
- Unique resource names via fixtures
- No shared state between workers
Test Independence
Requirements:
- No hardcoded IDs (use fixtures)
- No shared files (use temp files)
- No hardcoded ports (use random ports)
Bad Example:
def test_create_agent():
agent = AgentRegistry(id="test-agent", ...) # Collision!
Good Example:
def test_create_agent(unique_name):
agent = AgentRegistry(id=unique_name(), ...) # Safe
CI/CD Integration
CI-Specific Behavior
Video Recording: Enabled in CI only
if is_ci_environment():
context_args["record_video_dir"] = video_dir
Test Retries: Enabled in CI only
if is_ci_environment():
sys.argv.extend(["--reruns", "2"])
Artifact Upload: Screenshots and videos uploaded as workflow artifacts
GitHub Actions Example
- name: Run E2E tests
run: pytest tests/e2e_ui/ -n auto
- name: Upload screenshots
if: failure()
uses: actions/upload-artifact@v3
with:
name: screenshots
path: backend/tests/e2e_ui/artifacts/screenshots/
Best Practices
DO ✅
- Use fixtures for setup/teardown
- Write isolated tests (no dependencies)
- Use unique resource names
- Leverage automatic rollback
- Attach screenshots to Allure on failure
DON'T ❌
- Hardcode IDs or ports
- Share state between tests
- Manually cleanup database
- Skip fixture cleanup
- Ignore flaky tests (fix them)
Troubleshooting
Screenshots Not Capturing
Check:
- Is
pagefixture available? - Is
allure-pytestinstalled? - Is
allure-resultsdirectory writable?
Fix:
pip install allure-pytest
mkdir -p allure-results
Videos Not Recording
Check:
- Is running in CI (GITHUB_ACTIONS=true)?
- Is video dir created?
- Is browser context configured for video?
Fix:
if is_ci_environment():
os.makedirs(video_dir, exist_ok=True)
context_args["record_video_dir"] = video_dir
Tests Failing in Parallel but Passing Sequentially
Check:
- Are resources uniquely named?
- Is database isolation enabled?
- Are ports hardcoded?
Fix:
# Use unique_name fixture
agent = AgentRegistry(id=unique_name(), ...)
# Use db_session fixture (auto-isolation)
def test_something(db_session):
...
Additional Resources
- Test Isolation Patterns:
TEST_ISOLATION_PATTERNS.md - Flaky Test Guide:
FLAKY_TEST_GUIDE.md - Parallel Execution Guide:
PARALLEL_EXECUTION_GUIDE.md - Coverage Guide:
COVERAGE_GUIDE.md
Unified Test Runner (INFRA-08, INFRA-09, INFRA-10)
Overview
Single entry point for running all platform tests with unified Allure reporting.
Usage
# Run all platforms
python backend/tests/scripts/test_runner.py
# Run specific platform
python backend/tests/scripts/test_runner.py --platform backend
python backend/tests/scripts/test_runner.py --platform web
python backend/tests/scripts/test_runner.py --platform mobile
# Configure parallelism
python backend/tests/scripts/test_runner.py --workers 8
# Skip Allure report (faster iteration)
python backend/tests/scripts/test_runner.py --no-report
# Extra pytest arguments
python backend/tests/scripts/test_runner.py --extra "-k test_agent"
Platforms
| Platform | Test Framework | Allure Directory |
|---|---|---|
| Backend | pytest | allure-results/backend/ |
| Web E2E | pytest-playwright | allure-results/web/ |
| Mobile API | pytest | allure-results/mobile/ |
| Desktop | cargo test | (separate workflow) |
Allure Report
# Generate report manually
python backend/tests/scripts/allure_aggregator.py aggregate-allure \
--backend allure-results/backend/ \
--web allure-results/web/ \
--mobile allure-results/mobile/ \
--output allure-results/
# View report (auto-refreshes)
allure open allure-report
# Serve report on port 8080
allure serve allure-results
CI Integration
- GitHub Actions runs unified-tests job per platform
- generate-report job aggregates results
- Report uploaded as artifact for viewing
Output
- Allure results:
allure-results/ - Allure report:
allure-report/index.html - Screenshots:
artifacts/screenshots/(on failure) - Videos:
artifacts/videos/(on failure, CI only)
Last Updated: 2026-03-23 Phase: 233 - Test Infrastructure Foundation Plan: 05 - Unified Test Runner with Allure Cross-Platform Reporting