Files
calminer/tests/unit/test_reporting.py
zwitschi f020d276bc Enhance testing framework and UI feedback
- Updated architecture documentation to include details on UI rendering checks and Playwright end-to-end tests.
- Revised testing documentation to specify Playwright for frontend E2E tests and added details on running tests.
- Implemented feedback mechanism in scenario form for successful creation notifications.
- Added feedback div in ScenarioForm.html for user notifications.
- Created new fixtures for Playwright tests to manage server and browser instances.
- Developed comprehensive E2E tests for consumption, costs, equipment, maintenance, production, and scenarios.
- Added smoke tests to verify UI page loading and form submissions.
- Enhanced unit tests for simulation and validation, including new tests for report generation and validation errors.
- Created new test files for router validation to ensure consistent error handling.
- Established a new test suite for UI routes to validate dashboard and reporting functionalities.
- Implemented validation tests to ensure proper handling of JSON payloads.
2025-10-21 08:29:11 +02:00

120 lines
3.9 KiB
Python

import math
from typing import Any, Dict, List
import pytest
from fastapi.testclient import TestClient
from services.reporting import generate_report
def test_generate_report_empty():
report = generate_report([])
assert report == {
"count": 0,
"mean": 0.0,
"median": 0.0,
"min": 0.0,
"max": 0.0,
"std_dev": 0.0,
"variance": 0.0,
"percentile_10": 0.0,
"percentile_90": 0.0,
"percentile_5": 0.0,
"percentile_95": 0.0,
"value_at_risk_95": 0.0,
"expected_shortfall_95": 0.0,
}
def test_generate_report_with_values():
values: List[Dict[str, float]] = [
{"iteration": 1, "result": 10.0},
{"iteration": 2, "result": 20.0},
{"iteration": 3, "result": 30.0},
]
report = generate_report(values)
assert report["count"] == 3
assert math.isclose(float(report["mean"]), 20.0)
assert math.isclose(float(report["median"]), 20.0)
assert math.isclose(float(report["min"]), 10.0)
assert math.isclose(float(report["max"]), 30.0)
assert math.isclose(float(report["std_dev"]), 8.1649658, rel_tol=1e-6)
assert math.isclose(float(report["variance"]), 66.6666666, rel_tol=1e-6)
assert math.isclose(float(report["percentile_10"]), 12.0)
assert math.isclose(float(report["percentile_90"]), 28.0)
assert math.isclose(float(report["percentile_5"]), 11.0)
assert math.isclose(float(report["percentile_95"]), 29.0)
assert math.isclose(float(report["value_at_risk_95"]), 11.0)
assert math.isclose(float(report["expected_shortfall_95"]), 10.0)
def test_generate_report_single_value():
report = generate_report([
{"iteration": 1, "result": 42.0},
])
assert report["count"] == 1
assert report["std_dev"] == 0.0
assert report["variance"] == 0.0
assert report["percentile_10"] == 42.0
assert report["expected_shortfall_95"] == 42.0
def test_generate_report_ignores_invalid_entries():
raw_values: List[Any] = [
{"iteration": 1, "result": 10.0},
"not-a-mapping",
{"iteration": 2},
{"iteration": 3, "result": None},
{"iteration": 4, "result": 20},
]
report = generate_report(raw_values)
assert report["count"] == 2
assert math.isclose(float(report["mean"]), 15.0)
assert math.isclose(float(report["min"]), 10.0)
assert math.isclose(float(report["max"]), 20.0)
@pytest.fixture
def client(api_client: TestClient) -> TestClient:
return api_client
def test_reporting_endpoint_invalid_input(client: TestClient):
resp = client.post("/api/reporting/summary", json={})
assert resp.status_code == 400
assert resp.json()["detail"] == "Invalid input format"
def test_reporting_endpoint_success(client: TestClient):
input_data: List[Dict[str, float]] = [
{"iteration": 1, "result": 10.0},
{"iteration": 2, "result": 20.0},
{"iteration": 3, "result": 30.0},
]
resp = client.post("/api/reporting/summary", json=input_data)
assert resp.status_code == 200
data: Dict[str, Any] = resp.json()
assert data["count"] == 3
assert math.isclose(float(data["mean"]), 20.0)
assert math.isclose(float(data["variance"]), 66.6666666, rel_tol=1e-6)
assert math.isclose(float(data["value_at_risk_95"]), 11.0)
assert math.isclose(float(data["expected_shortfall_95"]), 10.0)
validation_error_cases: List[tuple[List[Any], str]] = [
(["not-a-dict"], "Entry at index 0 must be an object"),
([{"iteration": 1}], "Entry at index 0 must include numeric 'result'"),
([{"iteration": 1, "result": "bad"}],
"Entry at index 0 must include numeric 'result'"),
]
@pytest.mark.parametrize("payload,expected_detail", validation_error_cases)
def test_reporting_endpoint_validation_errors(
client: TestClient, payload: List[Any], expected_detail: str
):
resp = client.post("/api/reporting/summary", json=payload)
assert resp.status_code == 400
assert resp.json()["detail"] == expected_detail