Skip to content

Commit cf2cc43

Browse files
committed
tests: Improved compound tests for syntax
1 parent 2d1dd01 commit cf2cc43

File tree

5 files changed

+74
-33
lines changed

5 files changed

+74
-33
lines changed

statemachine/factory.py

+9-3
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,21 @@ def __init__(cls, name, bases, attrs):
3030
def _set_special_states(cls):
3131
if not cls.states:
3232
return
33-
initials = [s for s in cls.states if s.initial and not s.parent]
34-
if len(initials) != 1:
33+
initials = [s for s in cls.states if s.initial]
34+
parallels = [s.id for s in cls.states if s.parallel]
35+
root_only_has_parallels = len(cls.states) == len(parallels)
36+
if len(initials) != 1 and not root_only_has_parallels:
3537
raise InvalidDefinition(
3638
_(
3739
"There should be one and only one initial state. "
3840
"Your currently have these: {0}"
3941
).format(", ".join(s.id for s in initials))
4042
)
41-
cls.initial_state = initials[0]
43+
if root_only_has_parallels:
44+
# TODO: Temp, whe should fix initial, and current state design
45+
cls.initial_state = cls.states[0]
46+
else:
47+
cls.initial_state = initials[0]
4248
cls.final_states = [state for state in cls.states if state.final]
4349

4450
def _disconnected_states(cls, starting_state):

statemachine/state.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1+
from copy import deepcopy
12
from typing import Any
23
from typing import TypeAlias
3-
from copy import deepcopy
44

55
from .callbacks import Callbacks
66
from .exceptions import StateMachineError

tests/examples/microwave_inheritance_machine.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,11 @@
3838

3939

4040
class MicroWave(StateMachine):
41-
class oven(State.Builder, name="Oven", initial=True, parallel=True):
42-
class engine(State.Builder, name="Engine"):
41+
class oven(State.Builder, name="Microwave oven", parallel=True):
42+
class engine(State.Builder):
4343
off = State("Off", initial=True)
4444

45-
class on(State.Builder, name="On"):
45+
class on(State.Builder):
4646
idle = State("Idle", initial=True)
4747
cooking = State("Cooking")
4848

@@ -55,9 +55,9 @@ class on(State.Builder, name="On"):
5555
turn_on = off.to(on)
5656
on.to(off, cond="cook_time_is_over") # eventless transition
5757

58-
class door(State.Builder, name="Door"):
59-
closed = State("Closed", initial=True)
60-
open = State("Open")
58+
class door(State.Builder):
59+
closed = State(initial=True)
60+
open = State()
6161

6262
door_open = closed.to(open)
6363
door_close = open.to(closed)

tests/test_callbacks_isolation.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def __init__(self, name):
1717
self.name = name
1818
self.can_finish = False
1919
self.finalized = False
20-
super(TestStateMachine, self).__init__()
20+
super().__init__()
2121

2222
def do_finish(self):
2323
return self.name, self.can_finish

tests/test_compound.py

+57-22
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,68 @@
11
import pytest
22

33
from statemachine import State
4-
from statemachine import StateMachine
54

65

76
@pytest.fixture()
8-
def compound_engine_cls():
9-
class TestMachine(StateMachine):
10-
class engine(State.Builder, name="Engine", initial=True):
11-
off = State("Off", initial=True)
12-
on = State("On")
7+
def microwave_cls():
8+
from tests.examples.microwave_inheritance_machine import MicroWave
139

14-
turn_on = off.to(on)
15-
turn_off = on.to(off)
10+
return MicroWave
1611

17-
return TestMachine
12+
13+
def assert_state(s, name, initial=False, final=False, parallel=False, substates=None):
14+
if substates is None:
15+
substates = []
16+
17+
assert isinstance(s, State)
18+
assert s.name == name
19+
assert s.initial is initial
20+
assert s.final is final
21+
assert s.parallel is parallel
22+
assert isinstance(s, State)
23+
assert set(s.substates) == set(substates)
1824

1925

2026
class TestNestedDeclarations:
21-
def test_capture_constructor_arguments(self, compound_engine_cls):
22-
sm = compound_engine_cls()
23-
assert isinstance(sm.engine, State)
24-
assert sm.engine.name == "Engine"
25-
assert sm.engine.initial is True
26-
27-
def test_list_children_states(self, compound_engine_cls):
28-
sm = compound_engine_cls()
29-
assert [s.id for s in sm.engine.substates] == ["off", "on"]
30-
31-
def test_list_events(self, compound_engine_cls):
32-
sm = compound_engine_cls()
33-
assert [e.name for e in sm.events] == ["turn_on", "turn_off"]
27+
def test_capture_constructor_arguments(self, microwave_cls):
28+
sm = microwave_cls()
29+
30+
assert_state(
31+
sm.oven,
32+
"Microwave oven",
33+
parallel=True,
34+
substates=[sm.oven.engine, sm.oven.door],
35+
)
36+
assert_state(
37+
sm.oven.engine,
38+
"Engine",
39+
initial=False,
40+
substates=[sm.oven.engine.on, sm.oven.engine.off],
41+
)
42+
assert_state(sm.oven.engine.off, "Off", initial=True)
43+
assert_state(
44+
sm.oven.engine.on,
45+
"On",
46+
substates=[sm.oven.engine.on.idle, sm.oven.engine.on.cooking],
47+
)
48+
assert_state(
49+
sm.oven.door,
50+
"Door",
51+
initial=False,
52+
substates=[sm.oven.door.closed, sm.oven.door.open],
53+
)
54+
assert_state(sm.oven.door.closed, "Closed", initial=True)
55+
assert_state(sm.oven.door.open, "Open")
56+
57+
def test_list_children_states(self, microwave_cls):
58+
sm = microwave_cls()
59+
assert [s.id for s in sm.oven.engine.substates] == ["off", "on"]
60+
61+
def test_list_events(self, microwave_cls):
62+
sm = microwave_cls()
63+
assert [e.name for e in sm.events] == [
64+
"turn_on",
65+
"turn_off",
66+
"door_open",
67+
"door_close",
68+
]

0 commit comments

Comments
 (0)