hackathon-ENGIN/tests/test_validation.py

68 lines
2.6 KiB
Python

from __future__ import annotations
import unittest
from pathlib import Path
import numpy as np
import pandas as pd
from engin.config import FREQ_COLS
from engin.errors import InputDataError
from engin.validation import SpectrumFrameValidator
ROOT = Path(__file__).resolve().parents[1]
class SpectrumFrameValidatorTests(unittest.TestCase):
@classmethod
def setUpClass(cls) -> None:
full = pd.read_csv(ROOT / "test.csv")
first_engine = full["engine_id"].iloc[0]
cls.valid = full[full["engine_id"].eq(first_engine)].reset_index(drop=True)
cls.validator = SpectrumFrameValidator()
def test_valid_complete_engine_is_normalized(self) -> None:
result = self.validator.validate(self.valid)
self.assertEqual(len(result.frame), int(self.valid["n_cylinders"].iloc[0]))
self.assertTrue(pd.api.types.is_integer_dtype(result.frame["cylinder"]))
def test_missing_frequency_column_is_rejected(self) -> None:
with self.assertRaisesRegex(InputDataError, "mV_20"):
self.validator.validate(self.valid.drop(columns="mV_20"))
def test_duplicate_cylinder_is_rejected(self) -> None:
duplicated = pd.concat([self.valid, self.valid.iloc[[0]]], ignore_index=True)
with self.assertRaisesRegex(InputDataError, "zduplikowane"):
self.validator.validate(duplicated)
def test_incomplete_engine_reports_missing_cylinder(self) -> None:
incomplete = self.valid[self.valid["cylinder"].ne(3)].reset_index(drop=True)
with self.assertRaisesRegex(InputDataError, r"brak \[3\]"):
self.validator.validate(incomplete)
def test_non_numeric_measurement_is_rejected_with_location(self) -> None:
broken = self.valid.copy()
broken["mV_7"] = broken["mV_7"].astype(object)
broken.loc[0, "mV_7"] = "sensor_error"
with self.assertRaisesRegex(InputDataError, "mV_7"):
self.validator.validate(broken)
def test_excessive_missing_row_is_rejected(self) -> None:
broken = self.valid.copy()
broken.loc[0, FREQ_COLS[:12]] = np.nan
with self.assertRaisesRegex(InputDataError, "brakujących"):
self.validator.validate(broken)
def test_high_but_accepted_missing_rate_emits_warning(self) -> None:
noisy = self.valid.copy()
noisy.loc[:, FREQ_COLS[:3]] = np.nan
result = self.validator.validate(noisy)
self.assertEqual(len(result.warnings), 1)
def test_negative_amplitude_is_rejected(self) -> None:
broken = self.valid.copy()
broken.loc[0, "mV_0"] = -1
with self.assertRaisesRegex(InputDataError, "ujemna"):
self.validator.validate(broken)