Files
pygame-physics-opus5.5/tests/physics/test_vector.py
T
2026-09-24 15:45:31 +02:00

128 lines
3.5 KiB
Python

"""Tests der eigenen Vektorklasse."""
import copy
import math
import pickle
import pytest
from sandbox.physics.vector import ZERO, Vector2
def test_addition_and_subtraction() -> None:
assert Vector2(1, 2) + Vector2(3, -5) == Vector2(4, -3)
assert Vector2(1, 2) - Vector2(3, -5) == Vector2(-2, 7)
def test_scaling_from_both_sides_and_division() -> None:
assert Vector2(1.5, -2) * 2 == Vector2(3, -4)
assert 2 * Vector2(1.5, -2) == Vector2(3, -4)
assert Vector2(3, -4) / 2 == Vector2(1.5, -2)
def test_negation() -> None:
assert -Vector2(1, -2) == Vector2(-1, 2)
def test_dot_product() -> None:
assert Vector2(1, 2).dot(Vector2(3, 4)) == 11
assert Vector2(1, 0).dot(Vector2(0, 5)) == 0 # orthogonal
def test_cross_product_sign_and_value() -> None:
assert Vector2(1, 0).cross(Vector2(0, 1)) == 1
assert Vector2(0, 1).cross(Vector2(1, 0)) == -1
assert Vector2(2, 3).cross(Vector2(4, 6)) == 0 # parallel
def test_length_and_length_squared() -> None:
v = Vector2(3, 4)
assert v.length() == 5
assert v.length_squared() == 25
def test_normalized_has_unit_length_and_same_direction() -> None:
n = Vector2(3, 4).normalized()
assert n.length() == pytest.approx(1.0)
assert n.is_close(Vector2(0.6, 0.8))
def test_normalizing_the_zero_vector_returns_zero_instead_of_nan() -> None:
assert Vector2(0, 0).normalized() == ZERO
def test_perpendicular_is_rotated_by_plus_90_degrees() -> None:
v = Vector2(2, 1)
p = v.perpendicular()
assert p == Vector2(-1, 2)
assert v.dot(p) == 0
assert v.cross(p) > 0
def test_distance() -> None:
assert Vector2(1, 1).distance_to(Vector2(4, 5)) == 5
def test_clamped_limits_only_long_vectors() -> None:
short = Vector2(1, 1)
assert short.clamped(10) is short
clamped = Vector2(30, 40).clamped(10)
assert clamped.length() == pytest.approx(10)
assert clamped.is_close(Vector2(6, 8))
def test_lerp() -> None:
a = Vector2(0, 10)
b = Vector2(10, 20)
assert a.lerp(b, 0) == a
assert a.lerp(b, 1) == b
assert a.lerp(b, 0.5) == Vector2(5, 15)
def test_is_finite() -> None:
assert Vector2(1, 2).is_finite()
assert not Vector2(math.nan, 0).is_finite()
assert not Vector2(0, math.inf).is_finite()
def test_is_close_uses_absolute_tolerance() -> None:
assert Vector2(1, 1).is_close(Vector2(1 + 1e-12, 1))
assert not Vector2(1, 1).is_close(Vector2(1.1, 1))
assert Vector2(1, 1).is_close(Vector2(1.1, 1), tolerance=0.2)
def test_equality_hash_and_comparison_with_other_types() -> None:
assert Vector2(1, 2) == Vector2(1.0, 2.0)
assert Vector2(1, 2) != Vector2(2, 1)
assert Vector2(1, 2) != (1, 2)
assert len({Vector2(1, 2), Vector2(1, 2), Vector2(2, 1)}) == 2
def test_vectors_are_immutable() -> None:
v = Vector2(1, 2)
with pytest.raises(AttributeError):
v.x = 5 # type: ignore[misc]
with pytest.raises(AttributeError):
del v.y
assert v == Vector2(1, 2)
def test_operations_do_not_modify_operands() -> None:
a = Vector2(1, 2)
b = Vector2(3, 4)
_ = (a + b, a - b, a * 3, a / 2, -a, a.normalized(), a.clamped(0.1), a.lerp(b, 0.5))
assert a == Vector2(1, 2)
assert b == Vector2(3, 4)
def test_copy_and_pickle_round_trip() -> None:
v = Vector2(1.5, -2.5)
assert copy.copy(v) == v
assert copy.deepcopy(v) == v
assert pickle.loads(pickle.dumps(v)) == v
def test_repr_and_tuple() -> None:
assert repr(Vector2(1.5, 2)) == "Vector2(1.5, 2)"
assert Vector2(1.5, 2).to_tuple() == (1.5, 2)