Add report generation integration test

This commit is contained in:
2026-01-29 18:03:23 +00:00
parent 13a4fd16b3
commit a5a2cf2473

View File

@@ -0,0 +1,293 @@
"""Integration tests for report generation.
Tests the full report generation pipeline from test run to PDF output.
"""
import json
import tempfile
from datetime import datetime
from pathlib import Path
from uuid import UUID, uuid4
import pytest
from py_dvt_ate.data.models import Measurement, TestStatus
from py_dvt_ate.data.repository import SQLiteRepository
class TestReportGenerationIntegration:
"""Integration tests for the report generation pipeline."""
@pytest.fixture
def temp_dir(self) -> Path:
"""Create a temporary directory for test files."""
with tempfile.TemporaryDirectory() as tmpdir:
yield Path(tmpdir)
@pytest.fixture
def repository(self, temp_dir: Path) -> SQLiteRepository:
"""Create a test repository with sample data."""
db_path = temp_dir / "test.db"
measurements_dir = temp_dir / "measurements"
repo = SQLiteRepository(db_path, measurements_dir)
# Create a test run
test_config = {
"temperatures": [-40.0, 25.0, 85.0],
"input_voltage": 5.0,
"load_current": 0.1,
}
run_id = repo.create_run(
test_name="tempco",
config=test_config,
operator="test_operator",
description="Integration test run",
)
# Add some results
repo.save_result(
run_id=run_id,
parameter="tempco",
value=48.5,
unit="ppm/C",
lower_limit=None,
upper_limit=100.0,
)
repo.save_result(
run_id=run_id,
parameter="output_voltage_m40c",
value=3.2965,
unit="V",
lower_limit=3.2,
upper_limit=3.4,
)
repo.save_result(
run_id=run_id,
parameter="output_voltage_25c",
value=3.3000,
unit="V",
lower_limit=3.2,
upper_limit=3.4,
)
repo.save_result(
run_id=run_id,
parameter="output_voltage_85c",
value=3.2901,
unit="V",
lower_limit=3.2,
upper_limit=3.4,
)
# Add measurements
measurements = []
temperatures = [-40.0, 0.0, 25.0, 50.0, 85.0]
voltages = [3.2965, 3.2985, 3.3000, 3.2960, 3.2901]
for i, (temp, voltage) in enumerate(zip(temperatures, voltages, strict=False)):
measurements.append(
Measurement(
timestamp=float(i * 60),
parameter="output_voltage",
value=voltage,
unit="V",
temperature=temp,
input_voltage=5.0,
load_current=0.1,
)
)
repo.save_measurements(run_id, measurements)
# Complete the run
repo.complete_run(run_id, TestStatus.PASSED)
return repo
@pytest.fixture
def run_id(self, repository: SQLiteRepository) -> UUID:
"""Get the test run ID from the repository."""
runs = repository.get_all_runs()
return UUID(runs[0].id)
def test_full_report_generation(
self, repository: SQLiteRepository, run_id: UUID, temp_dir: Path
) -> None:
"""Test complete report generation pipeline."""
from py_dvt_ate.reporting import ReportConfig, ReportGenerator
# Create report config
config = ReportConfig(
company_name="Test Company Ltd",
include_charts=True,
chart_dpi=100, # Lower for faster tests
)
# Create generator
reports_dir = temp_dir / "reports"
generator = ReportGenerator(
repository=repository,
config=config,
reports_dir=reports_dir,
)
# Generate report
pdf_path = generator.generate(run_id)
# Verify PDF was created
assert pdf_path.exists()
assert pdf_path.suffix == ".pdf"
assert pdf_path.stat().st_size > 1000 # Should be non-trivial size
# Verify it's in the reports directory
assert pdf_path.parent == reports_dir
def test_report_generation_custom_path(
self, repository: SQLiteRepository, run_id: UUID, temp_dir: Path
) -> None:
"""Test report generation with custom output path."""
from py_dvt_ate.reporting import ReportConfig, ReportGenerator
config = ReportConfig(include_charts=False) # No charts for faster test
generator = ReportGenerator(
repository=repository,
config=config,
)
# Generate to custom path
custom_path = temp_dir / "custom_report.pdf"
pdf_path = generator.generate(run_id, output_path=custom_path)
assert pdf_path == custom_path
assert pdf_path.exists()
def test_report_generation_as_bytes(
self, repository: SQLiteRepository, run_id: UUID
) -> None:
"""Test generating report as bytes."""
from py_dvt_ate.reporting import ReportConfig, ReportGenerator
config = ReportConfig(include_charts=False)
generator = ReportGenerator(
repository=repository,
config=config,
)
# Generate as bytes
pdf_bytes = generator.generate_bytes(run_id)
# Verify it's a valid PDF
assert isinstance(pdf_bytes, bytes)
assert pdf_bytes.startswith(b"%PDF") # PDF magic bytes
assert len(pdf_bytes) > 1000
def test_report_includes_all_data(
self, repository: SQLiteRepository, run_id: UUID, temp_dir: Path
) -> None:
"""Test that generated report includes all expected data."""
from py_dvt_ate.reporting import ReportConfig, ReportGenerator
from py_dvt_ate.reporting.renderers.html import HTMLRenderer
config = ReportConfig(
company_name="Test Company",
include_charts=False,
)
generator = ReportGenerator(
repository=repository,
config=config,
)
# Get HTML (intermediate step) to check content
data = generator._gather_data(run_id)
html_renderer = HTMLRenderer()
html = html_renderer.render(data)
# Check for expected content
assert "tempco" in html
assert "Test Company" in html
assert "48.500000" in html # tempco value
assert "3.300000" in html # output voltage
assert "test_operator" in html
assert "Integration test run" in html
assert "PASS" in html
def test_report_with_failed_results(
self, temp_dir: Path
) -> None:
"""Test report generation with failed test results."""
from py_dvt_ate.reporting import ReportConfig, ReportGenerator
# Create repository with a failed test
db_path = temp_dir / "failed_test.db"
repo = SQLiteRepository(db_path, temp_dir / "measurements")
run_id = repo.create_run(
test_name="failed_test",
config={},
operator="test",
)
# Add failing result
repo.save_result(
run_id=run_id,
parameter="test_param",
value=150.0, # Exceeds limit
unit="X",
lower_limit=0.0,
upper_limit=100.0,
)
repo.complete_run(run_id, TestStatus.FAILED)
# Generate report
config = ReportConfig(include_charts=False)
generator = ReportGenerator(repository=repo, config=config)
pdf_bytes = generator.generate_bytes(run_id)
# Should still generate
assert pdf_bytes.startswith(b"%PDF")
def test_report_generation_invalid_run_id(
self, repository: SQLiteRepository, temp_dir: Path
) -> None:
"""Test that invalid run ID raises appropriate error."""
from py_dvt_ate.reporting import ReportConfig, ReportGenerationError, ReportGenerator
config = ReportConfig()
generator = ReportGenerator(repository=repository, config=config)
invalid_id = uuid4()
with pytest.raises(ReportGenerationError):
generator.generate(invalid_id)
def test_report_charts_generation(
self, repository: SQLiteRepository, run_id: UUID, temp_dir: Path
) -> None:
"""Test that charts are generated when enabled."""
from py_dvt_ate.reporting import ReportConfig, ReportGenerator
config = ReportConfig(include_charts=True, chart_dpi=72)
generator = ReportGenerator(
repository=repository,
config=config,
reports_dir=temp_dir / "reports",
)
# Gather data and check charts
data = generator._gather_data(run_id)
# Should have at least one chart (results bar chart)
assert len(data.charts) >= 1
# Voltage vs temperature chart should be present (we have voltage measurements)
assert "Voltage vs Temperature" in data.charts or "Results Summary" in data.charts