68 lines
2.6 KiB
Python
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)
|