93 lines
3.1 KiB
Python
93 lines
3.1 KiB
Python
import math
|
|
import pytest
|
|
from src.matrixmania.compute import rot_2D
|
|
|
|
|
|
# --- HELPER FUNCTION ---
|
|
def assert_matrices_close(m1, m2, abs_tol=1e-9):
|
|
"""
|
|
Helper function to compare two 2x2 matrices element-wise
|
|
using math.isclose for float comparison.
|
|
"""
|
|
assert len(m1) == 2 and len(m1[0]) == 2, "Matrix 1 is not 2x2"
|
|
assert len(m2) == 2 and len(m2[0]) == 2, "Matrix 2 is not 2x2"
|
|
|
|
for i in range(2):
|
|
for j in range(2):
|
|
# Assert that each element is close within the tolerance
|
|
assert math.isclose(m1[i][j], m2[i][j], abs_tol=abs_tol), \
|
|
f"Mismatch at [{i}][{j}]: {m1[i][j]} != {m2[i][j]}"
|
|
|
|
def test_90_degree_rotation_in_radians():
|
|
"""Tests a 90-degree rotation (input is pi/2 radians)."""
|
|
# 90 degrees = pi / 2 radians
|
|
# cos(pi/2) = 0, sin(pi/2) = 1
|
|
# Expected: [[0, -1], [1, 0]]
|
|
expected = [[0.0, -1.0], [1.0, 0.0]]
|
|
# Use the helper function for comparison
|
|
assert_matrices_close(rot_2D(math.pi / 2), expected)
|
|
|
|
|
|
def test_0_radian_rotation():
|
|
"""Tests a 0-radian rotation (should return the identity matrix)."""
|
|
# cos(0) = 1, sin(0) = 0
|
|
# Expected: [[1, 0], [0, 1]]
|
|
expected = [[1.0, 0.0], [0.0, 1.0]]
|
|
assert_matrices_close(rot_2D(0), expected)
|
|
assert_matrices_close(rot_2D(0.0), expected)
|
|
|
|
|
|
def test_180_degree_rotation_in_radians():
|
|
"""Tests a 180-degree rotation (input is pi radians)."""
|
|
# 180 degrees = pi radians
|
|
# cos(pi) = -1, sin(pi) = 0
|
|
# Expected: [[-1, 0], [0, -1]]
|
|
expected = [[-1.0, 0.0], [0.0, -1.0]]
|
|
assert_matrices_close(rot_2D(math.pi), expected)
|
|
|
|
|
|
def test_360_degree_rotation_in_radians():
|
|
"""Tests a 360-degree rotation (input is 2*pi radians)."""
|
|
# 360 degrees = 2*pi radians
|
|
# cos(2*pi) = 1, sin(2*pi) = 0
|
|
expected = [[1.0, 0.0], [0.0, 1.0]]
|
|
assert_matrices_close(rot_2D(math.pi * 2), expected)
|
|
|
|
|
|
def test_negative_90_degree_rotation_in_radians():
|
|
"""Tests a clockwise 90-degree rotation (input is -pi/2 radians)."""
|
|
# -90 degrees = -pi/2 radians
|
|
# cos(-pi/2) = 0, sin(-pi/2) = -1
|
|
# Expected: [[0, 1], [-1, 0]]
|
|
expected = [[0.0, 1.0], [-1.0, 0.0]]
|
|
assert_matrices_close(rot_2D(-math.pi / 2), expected)
|
|
|
|
|
|
def test_45_degree_rotation_in_radians():
|
|
"""Tests a 45-degree rotation (input is pi/4 radians)."""
|
|
# 45 degrees = pi/4 radians
|
|
val = math.sqrt(2) / 2 # This is cos(pi/4) and sin(pi/4)
|
|
# Expected: [[val, -val], [val, val]]
|
|
expected = [[val, -val], [val, val]]
|
|
assert_matrices_close(rot_2D(math.pi / 4), expected)
|
|
|
|
|
|
# --- Tests for error handling (Invalid Inputs) ---
|
|
# (These tests remain the same)
|
|
|
|
def test_error_on_string_input():
|
|
"""Tests that a ValueError is raised for string input."""
|
|
with pytest.raises(ValueError, match="instance of a numeric datatype"):
|
|
rot_2D("90")
|
|
|
|
|
|
def test_error_on_list_input():
|
|
"""Tests that a ValueError is raised for list input."""
|
|
with pytest.raises(ValueError, match="instance of a numeric datatype"):
|
|
rot_2D([math.pi])
|
|
|
|
|
|
def test_error_on_none_input():
|
|
"""Tests that a ValueError is raised for None input."""
|
|
with pytest.raises(ValueError, match="instance of a numeric datatype"):
|
|
rot_2D(None) |