diff --git a/data_analysis_script/tests/test_core.py b/data_analysis_script/tests/test_core.py new file mode 100644 index 0000000..298ef92 --- /dev/null +++ b/data_analysis_script/tests/test_core.py @@ -0,0 +1,54 @@ +import pytest +import math +import numpy as np + +from data_analysis_script import core + + +def example_data(): + # Representative measurement records + return [ + {"condition_name": "A", "amplitude": 1.0, "timestamp": 0.1}, + {"condition_name": "A", "amplitude": 2.0, "timestamp": 0.2}, + {"condition_name": "B", "amplitude": 5.0, "timestamp": 0.3}, + {"condition_name": "B", "amplitude": 7.0, "timestamp": 0.4}, + {"condition_name": "B", "amplitude": 20.0, "timestamp": 0.5}, # outlier + ] + + +def test_analyze_data_returns_expected_structure(): + data = example_data() + result = core.analyze_data(data) + assert isinstance(result, dict) + assert set(result.keys()) == {"median_amplitude", "outlier_rate", "statistical_significance"} + assert isinstance(result["median_amplitude"], (float, int)) + assert isinstance(result["outlier_rate"], (float, int)) + assert isinstance(result["statistical_significance"], (float, int, np.floating)) + + +def test_median_and_outlier_logic(): + data = example_data() + result = core.analyze_data(data) + median_manual = np.median([d["amplitude"] for d in data]) + assert math.isclose(result["median_amplitude"], median_manual, rel_tol=1e-6) + + # For outlier rate, expect roughly one outlier (20 vs lower values) + total = len(data) + outlier_estimate = 1 / total + assert abs(result["outlier_rate"] - outlier_estimate) < 0.3 + + +def test_statistical_significance_between_conditions(): + data = example_data() + result = core.analyze_data(data) + # p-value should be between 0 and 1 + assert 0.0 <= result["statistical_significance"] <= 1.0 + + +def test_handles_empty_or_invalid_input(): + with pytest.raises(ValueError): + core.analyze_data([]) + + invalid = [{"condition_name": "A", "amplitude": "x", "timestamp": 0.1}] + with pytest.raises(ValueError): + core.analyze_data(invalid)