File size: 1,859 Bytes
9e89884
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
"""Tests for the expression -> movement planner.

The planner is pure logic (no robot SDK), so it is fully unit-testable. We
inject a seeded RNG to make the "random" movement selection deterministic.
"""

import random

import pytest

from face_detection.behavior import Movement, MovementPlanner


def test_known_expressions_have_movements():
    planner = MovementPlanner()
    for expression in ("happy", "neutral"):
        move = planner.plan(expression)
        assert isinstance(move, Movement)
        assert move.duration > 0


def test_unknown_expression_falls_back_to_neutral():
    planner = MovementPlanner(rng=random.Random(0))
    fallback = planner.plan("does-not-exist")
    assert fallback in planner.movements_for("neutral")


def test_selection_is_deterministic_with_seeded_rng():
    a = MovementPlanner(rng=random.Random(42)).plan("happy")
    b = MovementPlanner(rng=random.Random(42)).plan("happy")
    assert a == b


def test_selection_varies_across_seeds_for_multi_option_expression():
    planner = MovementPlanner(rng=random.Random(123))
    picks = {planner.plan("happy").description for _ in range(50)}
    # "happy" defines more than one movement, so we expect variety.
    assert len(picks) > 1


def test_idle_movement_available():
    planner = MovementPlanner()
    idle = planner.idle()
    assert isinstance(idle, Movement)


def test_movement_fields_are_within_safe_ranges():
    planner = MovementPlanner()
    for expression in planner.expressions:
        for move in planner.movements_for(expression):
            if move.antennas is not None:
                left, right = move.antennas
                assert -1.5 <= left <= 1.5
                assert -1.5 <= right <= 1.5
            if move.body_yaw is not None:
                assert -1.0 <= move.body_yaw <= 1.0
            assert 0.1 <= move.duration <= 5.0