Skip to content

Commit 2397d84

Browse files
committed
refactor(tests): migrate testcases, Django and SCXML tests to StateChart
1 parent 287bf7c commit 2397d84

8 files changed

Lines changed: 69 additions & 50 deletions

File tree

tests/django_project/workflow/statemachines.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
from statemachine.states import States
22

3-
from statemachine import StateMachine
3+
from statemachine import StateChart
44

55
from .models import WorkflowSteps
66

77

8-
class WorfklowStateMachine(StateMachine):
8+
class WorfklowStateMachine(StateChart):
9+
allow_event_without_transition = False
10+
911
_ = States.from_enum(WorkflowSteps, initial=WorkflowSteps.DRAFT, final=WorkflowSteps.PUBLISHED)
1012

1113
publish = _.DRAFT.to(_.PUBLISHED, cond="is_active")

tests/scxml/test_microwave.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def test_microwave_scxml():
4040
processor.parse_scxml("microwave", MICROWAVE_SCXML)
4141
sm = processor.start()
4242

43-
assert sm.current_state.id == "unplugged"
43+
assert "unplugged" in sm.current_state_value
4444
sm.send("plug-in")
4545

4646
assert "idle" in sm.current_state_value

tests/test_error_execution.py

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
from statemachine import Event
55
from statemachine import State
66
from statemachine import StateChart
7-
from statemachine import StateMachine
87

98

109
class ErrorInGuardSC(StateChart):
@@ -54,8 +53,10 @@ def bad_after(self):
5453
raise RuntimeError("after failed")
5554

5655

57-
class ErrorInGuardSM(StateMachine):
58-
"""StateMachine subclass: exceptions should propagate."""
56+
class ErrorInGuardSM(StateChart):
57+
"""StateChart subclass with error_on_execution=False: exceptions should propagate."""
58+
59+
error_on_execution = False
5960

6061
initial = State("initial", initial=True)
6162

@@ -65,10 +66,8 @@ def bad_guard(self):
6566
raise RuntimeError("guard failed")
6667

6768

68-
class ErrorInActionSMWithFlag(StateMachine):
69-
"""StateMachine subclass with error_on_execution = True."""
70-
71-
error_on_execution = True
69+
class ErrorInActionSMWithFlag(StateChart):
70+
"""StateChart subclass (error_on_execution = True by default)."""
7271

7372
s1 = State("s1", initial=True)
7473
s2 = State("s2")
@@ -144,7 +143,7 @@ def test_exception_in_after_sends_error_execution_no_rollback():
144143

145144

146145
def test_statemachine_exception_propagates():
147-
"""StateMachine (error_on_execution=False) should propagate exceptions normally."""
146+
"""StateChart with error_on_execution=False should propagate exceptions normally."""
148147
sm = ErrorInGuardSM()
149148
assert sm.configuration == {sm.initial}
150149

@@ -184,7 +183,7 @@ def test_error_in_error_handler_no_infinite_loop():
184183

185184

186185
def test_statemachine_with_error_on_execution_true():
187-
"""Custom StateMachine subclass with error_on_execution=True should catch errors."""
186+
"""StateChart (error_on_execution=True by default) should catch errors."""
188187
sm = ErrorInActionSMWithFlag()
189188
assert sm.configuration == {sm.s1}
190189

@@ -496,11 +495,9 @@ def obsess(self):
496495
assert sm.configuration == {sm.betrayed}
497496

498497
def test_statemachine_with_convention_and_flag(self):
499-
"""StateMachine with error_on_execution=True uses the error_ convention."""
500-
501-
class SarumanBetrayal(StateMachine):
502-
error_on_execution = True
498+
"""StateChart (error_on_execution=True by default) uses the error_ convention."""
503499

500+
class SarumanBetrayal(StateChart):
504501
white_council = State("white_council", initial=True)
505502
orthanc = State("orthanc", final=True)
506503

@@ -515,9 +512,11 @@ def betray(self):
515512
assert sm.configuration == {sm.orthanc}
516513

517514
def test_statemachine_without_flag_propagates(self):
518-
"""StateMachine without error_on_execution=True propagates errors even with convention."""
515+
"""StateChart with error_on_execution=False propagates errors even with convention."""
516+
517+
class AragornSword(StateChart):
518+
error_on_execution = False
519519

520-
class AragornSword(StateMachine):
521520
broken = State("broken", initial=True)
522521

523522
reforge = broken.to(broken, on="attempt_reforge")
@@ -955,7 +954,9 @@ def after_go(self, **kwargs):
955954
def test_runtime_error_in_after_without_error_on_execution_propagates(self):
956955
"""RuntimeError in after callback without error_on_execution raises."""
957956

958-
class SM(StateMachine):
957+
class SM(StateChart):
958+
error_on_execution = False
959+
959960
s1 = State(initial=True)
960961
s2 = State(final=True)
961962

@@ -989,7 +990,9 @@ def after_go(self, **kwargs):
989990
def test_runtime_error_in_microstep_without_error_on_execution(self):
990991
"""RuntimeError in microstep without error_on_execution raises."""
991992

992-
class SM(StateMachine):
993+
class SM(StateChart):
994+
error_on_execution = False
995+
993996
s1 = State(initial=True)
994997
s2 = State()
995998

@@ -1007,7 +1010,9 @@ def on_enter_s2(self, **kwargs):
10071010
def test_internal_queue_processes_raised_events():
10081011
"""Internal events raised during processing are handled."""
10091012

1010-
class SM(StateMachine):
1013+
class SM(StateChart):
1014+
error_on_execution = False
1015+
10111016
s1 = State(initial=True)
10121017
s2 = State()
10131018
s3 = State(final=True)
@@ -1027,7 +1032,9 @@ def on_enter_s2(self, **kwargs):
10271032
def test_engine_start_when_already_started():
10281033
"""start() is a no-op when state machine is already initialized."""
10291034

1030-
class SM(StateMachine):
1035+
class SM(StateChart):
1036+
error_on_execution = False
1037+
10311038
s1 = State(initial=True)
10321039
s2 = State(final=True)
10331040

@@ -1092,7 +1099,9 @@ def bad_action(self):
10921099
def test_runtime_error_in_internal_event_propagates_without_error_on_execution():
10931100
"""RuntimeError in internal event propagates when error_on_execution is False."""
10941101

1095-
class SM(StateMachine):
1102+
class SM(StateChart):
1103+
error_on_execution = False
1104+
10961105
s1 = State(initial=True)
10971106
s2 = State()
10981107
s3 = State()

tests/testcases/issue308.md

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ A StateMachine that exercises the example given on issue
66
In this example, we share the transition list between events.
77

88
```py
9-
>>> from statemachine import StateMachine, State
9+
>>> from statemachine import StateChart, State
1010

11-
>>> class TestSM(StateMachine):
11+
>>> class TestSM(StateChart):
1212
... state1 = State('s1', initial=True)
1313
... state2 = State('s2')
1414
... state3 = State('s3')
@@ -91,31 +91,37 @@ Example given:
9191
>>> m = TestSM()
9292
enter state1
9393

94-
>>> m.state1.is_active, m.state2.is_active, m.state3.is_active, m.state4.is_active, m.current_state ; _ = m.cycle()
95-
(True, False, False, False, State('s1', id='state1', value='state1', initial=True, final=False, parallel=False))
94+
>>> m.state1.is_active, m.state2.is_active, m.state3.is_active, m.state4.is_active, list(m.configuration_values)
95+
(True, False, False, False, ['state1'])
96+
97+
>>> _ = m.cycle()
9698
before cycle
9799
exit state1
98100
on cycle
99101
enter state2
100102
after cycle
101103

102-
>>> m.state1.is_active, m.state2.is_active, m.state3.is_active, m.state4.is_active, m.current_state ; _ = m.cycle()
103-
(False, True, False, False, State('s2', id='state2', value='state2', initial=False, final=False, parallel=False))
104+
>>> m.state1.is_active, m.state2.is_active, m.state3.is_active, m.state4.is_active, list(m.configuration_values)
105+
(False, True, False, False, ['state2'])
106+
107+
>>> _ = m.cycle()
104108
before cycle
105109
exit state2
106110
on cycle
107111
enter state3
108112
after cycle
109113

110-
>>> m.state1.is_active, m.state2.is_active, m.state3.is_active, m.state4.is_active, m.current_state ; _ = m.cycle()
111-
(False, False, True, False, State('s3', id='state3', value='state3', initial=False, final=False, parallel=False))
114+
>>> m.state1.is_active, m.state2.is_active, m.state3.is_active, m.state4.is_active, list(m.configuration_values)
115+
(False, False, True, False, ['state3'])
116+
117+
>>> _ = m.cycle()
112118
before cycle
113119
exit state3
114120
on cycle
115121
enter state4
116122
after cycle
117123

118-
>>> m.state1.is_active, m.state2.is_active, m.state3.is_active, m.state4.is_active, m.current_state
119-
(False, False, False, True, State('s4', id='state4', value='state4', initial=False, final=True, parallel=False))
124+
>>> m.state1.is_active, m.state2.is_active, m.state3.is_active, m.state4.is_active, list(m.configuration_values)
125+
(False, False, False, True, ['state4'])
120126

121127
```

tests/testcases/issue384_multiple_observers.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ This works also as a regression test.
99

1010
```py
1111
>>> from statemachine import State
12-
>>> from statemachine import StateMachine
12+
>>> from statemachine import StateChart
1313

1414
>>> class MyObs:
1515
... def on_move_car(self):
@@ -21,7 +21,7 @@ This works also as a regression test.
2121
...
2222

2323

24-
>>> class Car(StateMachine):
24+
>>> class Car(StateChart):
2525
... stopped = State(initial=True)
2626
... moving = State()
2727
...

tests/testcases/issue449.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ A StateMachine that exercises the example given on issue
77

88

99
```py
10-
>>> from statemachine import StateMachine, State
10+
>>> from statemachine import StateChart, State
1111

12-
>>> class ExampleStateMachine(StateMachine):
12+
>>> class ExampleStateMachine(StateChart):
1313
... initial = State(initial=True)
1414
... second = State()
1515
... third = State()
@@ -40,16 +40,16 @@ Exercise:
4040
>>> example = ExampleStateMachine()
4141
Entering state initial. Event: __initial__
4242

43-
>>> print(example.current_state)
44-
Initial
43+
>>> print(list(example.configuration_values))
44+
['initial']
4545

4646
>>> example.send("initial_to_second") # this will call second_to_third and third_to_fourth
4747
Entering state second. Event: initial_to_second
4848
Entering state third. Event: second_to_third
4949
Entering state fourth. Event: third_to_fourth
5050
third_to_fourth on on_enter_state worked
5151

52-
>>> print("My current state is", example.current_state)
53-
My current state is Fourth
52+
>>> print("My current state is", list(example.configuration_values))
53+
My current state is ['fourth']
5454

5555
```

tests/testcases/test_issue434.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,17 @@
33
import pytest
44

55
from statemachine import State
6-
from statemachine import StateMachine
6+
from statemachine import StateChart
77

88

99
class Model:
1010
def __init__(self, data: dict):
1111
self.data = data
1212

1313

14-
class DataCheckerMachine(StateMachine):
14+
class DataCheckerMachine(StateChart):
15+
error_on_execution = False
16+
1517
check_data = State(initial=True)
1618
data_good = State(final=True)
1719
data_bad = State(final=True)
@@ -50,24 +52,24 @@ def test_max_cycle_without_success(data_checker_machine):
5052
sm = data_checker_machine
5153
cycle_rate = 0.1
5254

53-
while not sm.current_state.final:
55+
while not sm.is_terminated:
5456
sm.cycle()
5557
sleep(cycle_rate)
5658

57-
assert sm.current_state == sm.data_bad
59+
assert sm.data_bad.is_active
5860
assert sm.cycle_count == 12
5961

6062

6163
def test_data_turns_good_mid_cycle(initial_data):
6264
sm = DataCheckerMachine(Model(initial_data))
6365
cycle_rate = 0.1
6466

65-
while not sm.current_state.final:
67+
while not sm.is_terminated:
6668
sm.cycle()
6769
if sm.cycle_count == 5:
6870
print("Now data looks good!")
6971
sm.model.data["value"] = 20
7072
sleep(cycle_rate)
7173

72-
assert sm.current_state == sm.data_good
74+
assert sm.data_good.is_active
7375
assert sm.cycle_count == 6 # Transition occurs at the 6th cycle

tests/testcases/test_issue480.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@
1212
from unittest.mock import call
1313

1414
from statemachine import State
15-
from statemachine import StateMachine
15+
from statemachine import StateChart
1616

1717

18-
class MyStateMachine(StateMachine):
18+
class MyStateMachine(StateChart):
1919
state_1 = State(initial=True)
2020
state_2 = State(final=True)
2121

@@ -53,4 +53,4 @@ def test_initial_state_activation_handler():
5353
]
5454

5555
assert sm.mock.mock_calls == expected_calls
56-
assert sm.current_state == sm.state_2
56+
assert sm.state_2.is_active

0 commit comments

Comments
 (0)