| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- import unittest
- import pandas as pd
- from defect_analysis.data_quality import build_data_quality_report
- from defect_analysis.root_cause import build_extended_root_causes
- from defect_analysis.schemas import (
- CORE_REQUIRED_COLUMNS,
- TEMPLATE_COLUMNS,
- get_missing_required_columns,
- normalize_defect_schema,
- )
- class ProductionModulesTest(unittest.TestCase):
- def test_schema_exposes_core_and_template_columns(self):
- self.assertIn("defect_id", CORE_REQUIRED_COLUMNS)
- self.assertIn("lam_fixture_id", TEMPLATE_COLUMNS)
- self.assertIn("material_lot_oca", TEMPLATE_COLUMNS)
- def test_schema_normalization_keeps_legacy_csv_compatible(self):
- legacy = pd.DataFrame(
- {
- "defect_id": ["D1"],
- "panel_id": ["P1"],
- "batch_id": ["B1"],
- "equipment_id": ["LAM-A01"],
- "seat_id": ["R1C1"],
- "inspection_station": ["AOI-1"],
- "timestamp": [pd.Timestamp("2026-04-01 08:00:00")],
- "defect_type": ["划痕"],
- "severity": ["严重"],
- "x_mm": [10.0],
- "y_mm": [20.0],
- "panel_width_mm": [155.0],
- "panel_height_mm": [340.0],
- "hour": [8],
- "shift": ["白班"],
- "day": ["2026-04-01"],
- }
- )
- normalized = normalize_defect_schema(legacy)
- self.assertEqual([], get_missing_required_columns(normalized))
- self.assertEqual("point", normalized.loc[0, "defect_geometry_type"])
- self.assertEqual("LAM-A01", normalized.loc[0, "lam_equipment_id"])
- def test_data_quality_report_flags_invalid_coordinates_and_traceability(self):
- df = normalize_defect_schema(
- pd.DataFrame(
- {
- "defect_id": ["D1", "D2"],
- "panel_id": ["P1", ""],
- "batch_id": ["B1", "B1"],
- "equipment_id": ["LAM-A01", "LAM-A01"],
- "seat_id": ["R1C1", "R1C2"],
- "inspection_station": ["AOI-1", "AOI-1"],
- "timestamp": [pd.Timestamp("2026-04-01"), pd.Timestamp("2026-04-01")],
- "defect_type": ["划痕", "未知缺陷"],
- "severity": ["严重", "轻微"],
- "x_mm": [10.0, 999.0],
- "y_mm": [20.0, 20.0],
- "panel_width_mm": [155.0, 155.0],
- "panel_height_mm": [340.0, 340.0],
- "hour": [8, 8],
- "shift": ["白班", "白班"],
- "day": ["2026-04-01", "2026-04-01"],
- "lam_fixture_id": ["FIX-1", ""],
- }
- )
- )
- report = build_data_quality_report(df)
- self.assertLess(report["score"], 100)
- self.assertLess(report["coordinate_valid_rate"], 1.0)
- self.assertLess(report["traceability_rate"], 1.0)
- self.assertTrue(any("坐标" in issue for issue in report["issues"]))
- def test_data_quality_report_handles_missing_columns(self):
- report = build_data_quality_report(pd.DataFrame({"defect_id": ["D1"]}))
- self.assertLess(report["score"], 100)
- self.assertEqual(0.0, report["coordinate_valid_rate"])
- self.assertTrue(report["issues"])
- def test_root_cause_module_returns_extended_candidates(self):
- rows = []
- for i in range(10):
- rows.append(
- {
- "defect_id": f"D{i}",
- "panel_id": f"P{i}",
- "batch_id": "B1",
- "equipment_id": "LAM-A01",
- "seat_id": "R1C1",
- "inspection_station": "AOI-1",
- "timestamp": pd.Timestamp("2026-04-01"),
- "defect_type": "划痕",
- "severity": "严重" if i < 3 else "轻微",
- "x_mm": 10.0,
- "y_mm": 20.0,
- "panel_width_mm": 155.0,
- "panel_height_mm": 340.0,
- "hour": 8,
- "shift": "白班",
- "day": "2026-04-01",
- "lam_fixture_id": "FIX-HOT" if i < 8 else "FIX-OK",
- }
- )
- df = normalize_defect_schema(pd.DataFrame(rows))
- candidates = build_extended_root_causes(df, dimensions=["lam_fixture_id"])
- self.assertEqual("lam_fixture_id", candidates.iloc[0]["维度"])
- self.assertEqual("FIX-HOT", candidates.iloc[0]["候选值"])
- self.assertGreater(candidates.iloc[0]["异常倍数"], 1.0)
- def test_root_cause_empty_dimensions_do_not_fallback_to_defaults(self):
- df = normalize_defect_schema(
- pd.DataFrame(
- {
- "defect_id": ["D1"],
- "panel_id": ["P1"],
- "batch_id": ["B1"],
- "equipment_id": ["LAM-A01"],
- "seat_id": ["R1C1"],
- "inspection_station": ["AOI-1"],
- "timestamp": [pd.Timestamp("2026-04-01")],
- "defect_type": ["划痕"],
- "severity": ["严重"],
- "x_mm": [10.0],
- "y_mm": [20.0],
- "panel_width_mm": [155.0],
- "panel_height_mm": [340.0],
- "hour": [8],
- "shift": ["白班"],
- "day": ["2026-04-01"],
- "lam_fixture_id": ["FIX-1"],
- }
- )
- )
- candidates = build_extended_root_causes(df, dimensions=[])
- self.assertTrue(candidates.empty)
- if __name__ == "__main__":
- unittest.main()
|