from app.analysis.spc import SPCResult, calculate_spc from app.parsers.models import MeasurementRecord def _make_records(name: str, nominal: float, tol: float, actuals: list[float]): return [ MeasurementRecord( feature_name=name, nominal=nominal, tolerance_plus=tol, tolerance_minus=-tol, actual=a, deviation=a - nominal, ) for a in actuals ] def test_single_measurement_returns_none_indices(): records = _make_records("D1", 10.0, 0.05, [10.01]) results = calculate_spc(records) assert len(results) == 1 r = results[0] assert r.cp is None assert r.cpk is None assert r.pp is None assert r.ppk is None def test_basic_spc_calculation(): actuals = [10.01, 10.02, 9.99, 10.00, 10.03, 9.98, 10.01, 10.02, 9.99, 10.00] records = _make_records("D1", 10.0, 0.05, actuals) results = calculate_spc(records) assert len(results) == 1 r = results[0] assert r.n == 10 assert r.pp is not None assert r.ppk is not None assert r.cp is not None assert r.cpk is not None assert r.pp > 0 assert r.cpk > 0 assert r.out_of_spec_count == 0 def test_out_of_spec_count(): actuals = [10.0, 10.06, 9.94, 10.0, 10.0] # 10.06 and 9.94 outside ±0.05 records = _make_records("D1", 10.0, 0.05, actuals) results = calculate_spc(records) assert results[0].out_of_spec_count == 2 def test_multiple_features(): records = ( _make_records("D1", 10.0, 0.05, [10.01, 10.02, 9.99]) + _make_records("D2", 20.0, 0.10, [20.05, 19.95, 20.01]) ) results = calculate_spc(records) assert len(results) == 2 names = {r.feature_name for r in results} assert names == {"D1", "D2"} def test_shapiro_not_computed_for_small_n(): records = _make_records("D1", 10.0, 0.05, [10.01, 10.02]) results = calculate_spc(records) assert results[0].shapiro_p is None def test_shapiro_computed_for_n_ge_3(): records = _make_records("D1", 10.0, 0.05, [10.01, 10.02, 9.99]) results = calculate_spc(records) assert results[0].shapiro_p is not None def test_to_dict(): records = _make_records("D1", 10.0, 0.05, [10.01, 10.02, 9.99, 10.00, 10.03]) results = calculate_spc(records) d = results[0].to_dict() assert "feature_name" in d assert "cpk" in d assert "values" in d assert isinstance(d["values"], list)