Coverage for tests/test_tests_checks.py: 100%
64 statements
« prev ^ index » next coverage.py v7.16.0, created at 2026-09-14 10:13 +0000
« prev ^ index » next coverage.py v7.16.0, created at 2026-09-14 10:13 +0000
1# This file is part of lsst-images.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (https://www.lsst.org).
6# See the COPYRIGHT file at the top-level directory of this distribution
7# for details of code ownership.
8#
9# Use of this source code is governed by a 3-clause BSD-style
10# license that can be found in the LICENSE file.
12from __future__ import annotations
14import astropy.units as u
15import numpy as np
16import pytest
18from lsst.images import Box, Mask, MaskPlane, MaskSchema
19from lsst.images.tests import annotate_errors, assert_masks_equal, assert_values_equal
22def test_assert_values_equal_passes():
23 """Assert equal arrays pass."""
24 assert_values_equal(np.array([1, 2, 3]), np.array([1, 2, 3]))
27def test_assert_values_equal_nan_equal_by_default():
28 """Assert NaN compares equal by default."""
29 a = np.array([1.0, np.nan])
30 assert_values_equal(a, a.copy())
33def test_assert_values_equal_exact_by_default():
34 """Assert a small difference fails by default (exact equality)."""
35 with pytest.raises(AssertionError, match="max abs diff"):
36 assert_values_equal(np.array([1.0]), np.array([1.0 + 1e-6]))
39def test_assert_values_equal_rtol_passes():
40 """Assert an explicit relative tolerance passes."""
41 assert_values_equal(np.array([1.0]), np.array([1.0 + 1e-6]), rtol=1e-5)
44def test_assert_values_equal_fails_with_report():
45 """Assert a mismatch raises a report message."""
46 a = np.array([1.0, 2.0, 3.0])
47 b = np.array([1.0, 2.0, 4.0])
48 with pytest.raises(AssertionError, match="1/3 values differ"):
49 assert_values_equal(a, b)
52def test_assert_values_equal_label_prefix():
53 """Assert the label prefixes the failure message."""
54 with pytest.raises(AssertionError, match=r"^mask\[BAD\]: "):
55 assert_values_equal(np.array([True]), np.array([False]), label="mask[BAD]")
58def test_assert_values_equal_shape_mismatch():
59 """Assert a shape mismatch raises."""
60 with pytest.raises(AssertionError, match="shape"):
61 assert_values_equal(np.zeros((2, 2)), np.zeros((3, 3)))
64def test_assert_values_equal_non_numeric_reports_indices():
65 """Assert non-numeric arrays report differing indices."""
66 a = np.array(["a", "b", "c"])
67 b = np.array(["a", "b", "z"])
68 with pytest.raises(AssertionError, match="values differ"):
69 assert_values_equal(a, b)
72def test_assert_values_equal_nan_not_equal_to_number():
73 """Assert NaN still does not equal a finite number."""
74 with pytest.raises(AssertionError):
75 assert_values_equal(np.array([np.nan]), np.array([1.0]))
78def test_assert_values_equal_atol_quantity_unit_aware():
79 """Assert a Quantity atol is converted to the unit of a."""
80 a = np.array([1.0, 2.0]) * u.deg
81 b = a.to(u.arcsec)
82 assert_values_equal(a, b, rtol=0.0, atol=1e-7 * u.arcsec)
85def test_assert_values_equal_unit_aware():
86 """Assert unit-aware comparison converts b to the unit of a."""
87 a = np.array([1.0, 2.0]) * u.deg
88 b = a.to(u.arcsec)
89 assert_values_equal(a, b, rtol=1e-5, atol=0.0)
92def test_assert_values_equal_incompatible_units_raise():
93 """Assert incompatible units raise."""
94 with pytest.raises(u.UnitConversionError):
95 assert_values_equal(np.array([1.0]) * u.deg, np.array([1.0]) * u.s)
98def test_label_assertions_notes():
99 """Assert a failing check is re-raised with the label as a note."""
100 with pytest.raises(AssertionError) as exc_info:
101 with annotate_errors("psf"):
102 raise AssertionError("inner")
103 assert exc_info.value.args == ("inner",)
104 assert exc_info.value.__notes__ == ["psf"]
107def test_label_assertions_passthrough_on_success():
108 """Assert a passing block is not re-raised."""
109 with annotate_errors("psf"):
110 pass # must not raise
113def test_assert_masks_equal_notes_plane_diff() -> None:
114 """Assert that a mask mismatch adds a per-plane +/- note."""
115 schema = MaskSchema([MaskPlane("A", "dA")], dtype=np.uint8)
116 m1 = Mask(0, schema=schema, bbox=Box.factory[0:2, 0:1])
117 m1.set("A", np.array([[True], [False]]))
118 m2 = Mask(0, schema=schema, bbox=Box.factory[0:2, 0:1])
119 m2.set("A", np.array([[True], [True]]))
120 with pytest.raises(AssertionError) as excinfo:
121 assert_masks_equal(m1, m2)
122 notes = excinfo.value.__notes__ or []
123 assert any("mask[A]: +0 -1" in n for n in notes)