a77edafcbf
Validate Operations / validate-operations (push) Has been cancelled
plot adjustments validation adjustments
76 lines
2.8 KiB
Python
76 lines
2.8 KiB
Python
from pathlib import Path
|
|
import sys
|
|
|
|
import numpy as np
|
|
import pytest
|
|
|
|
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
|
|
|
|
from raptor_validation.output_comparison import compare_output_arrays
|
|
|
|
|
|
def test_absolute_floor_does_not_accept_lost_small_output():
|
|
result = compare_output_arrays(np.zeros(2), np.array([1e-4, -2e-4]), atol=1e-3, rtol=1e-4)
|
|
assert result.pointwise_passed
|
|
assert result.relative_l2_error == pytest.approx(1)
|
|
assert not result.passed
|
|
|
|
|
|
@pytest.mark.parametrize("scale", [1e-200, 1e-4, 1, 1e200])
|
|
def test_small_relative_roundoff_is_independent_of_scale(scale):
|
|
expected = np.array([1, -2, 3], dtype=np.float64) * scale
|
|
result = compare_output_arrays(expected * (1 + 1e-6), expected, atol=1e-3, rtol=1e-4)
|
|
assert result.passed
|
|
assert result.relative_l2_error == pytest.approx(1e-6)
|
|
|
|
|
|
def test_norm_agreement_cannot_hide_an_incorrect_small_element():
|
|
result = compare_output_arrays([1e6, .01], [1e6, 0.0], atol=1e-3, rtol=1e-4)
|
|
assert result.relative_l2_error < 1e-4
|
|
assert not result.pointwise_passed
|
|
assert not result.passed
|
|
|
|
|
|
@pytest.mark.parametrize("actual,expected", [([np.inf], [1.0]), ([1.0], [np.inf]),
|
|
([np.inf], [np.inf]), ([np.nan], [np.nan])])
|
|
def test_nonfinite_outputs_never_pass(actual, expected):
|
|
assert not compare_output_arrays(actual, expected, atol=1e-3, rtol=1e-4).passed
|
|
|
|
|
|
@pytest.mark.parametrize("actual,expected", [([1.0], [[1.0]]), ([1.0], [])])
|
|
def test_broadcasting_cannot_hide_output_shape_errors(actual, expected):
|
|
with pytest.raises(ValueError, match="shapes differ"):
|
|
compare_output_arrays(actual, expected, atol=1e-3, rtol=1e-4)
|
|
|
|
|
|
def test_zero_reference_retains_absolute_check():
|
|
result = compare_output_arrays([1e-6], [0.0], atol=1e-3, rtol=1e-4)
|
|
assert result.passed and result.relative_l2_error is None
|
|
assert not compare_output_arrays([.01], [0.0], atol=1e-3, rtol=1e-4).passed
|
|
|
|
|
|
def test_zero_relative_tolerance_requests_absolute_only_check():
|
|
result = compare_output_arrays([0.0], [1e-4], atol=1e-3, rtol=0)
|
|
assert result.passed
|
|
|
|
|
|
def test_integer_outputs_require_exact_agreement_without_float_rounding():
|
|
expected = np.array([2**53], np.int64)
|
|
result = compare_output_arrays(expected + 1, expected, atol=1e-3, rtol=1e-4)
|
|
assert not result.passed and result.max_abs_diff == 1
|
|
|
|
|
|
def test_empty_outputs_match():
|
|
assert compare_output_arrays([], [], atol=1e-3, rtol=1e-4).passed
|
|
|
|
|
|
@pytest.mark.parametrize("atol,rtol", [(-1, 0), (0, -1), (np.inf, 0), (0, np.nan)])
|
|
def test_invalid_tolerances_are_rejected(atol, rtol):
|
|
with pytest.raises(ValueError, match="tolerances"):
|
|
compare_output_arrays([0.0], [0.0], atol=atol, rtol=rtol)
|
|
|
|
|
|
def test_complex_outputs_are_not_silently_cast_to_real():
|
|
with pytest.raises(ValueError, match="real numeric"):
|
|
compare_output_arrays([1 + 2j], [1 + 0j], atol=1e-3, rtol=1e-4)
|