Skip to content

Commit 4499656

Browse files
committed
feat(test): add performance tests to check it doesn't timeout in edge cases
1 parent debf12d commit 4499656

File tree

3 files changed

+90
-1
lines changed

3 files changed

+90
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
- feat(core): add `view` method to `Store` to allow computing a derived value from
66
the state only when it is accessed and caching the result until the relevant parts
77
of the state change
8+
- feat(test): add performance tests to check it doesn't timeout in edge cases
89

910
## Version 0.15.0
1011

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "python-redux"
3-
version = "0.15.0"
3+
version = "0.15.1"
44
description = "Redux implementation for Python"
55
authors = ["Sassan Haradji <[email protected]>"]
66
license = "Apache-2.0"

tests/test_performance.py

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# ruff: noqa: D100, D101, D102, D103, D104, D107
2+
3+
from __future__ import annotations
4+
5+
from dataclasses import replace
6+
from typing import Generator
7+
8+
import pytest
9+
from immutable import Immutable
10+
11+
from redux.basic_types import (
12+
BaseAction,
13+
CompleteReducerResult,
14+
CreateStoreOptions,
15+
FinishAction,
16+
FinishEvent,
17+
InitAction,
18+
InitializationActionError,
19+
)
20+
from redux.main import Store
21+
22+
23+
class StateType(Immutable):
24+
value: int
25+
26+
27+
class IncrementAction(BaseAction): ...
28+
29+
30+
Action = IncrementAction | InitAction | FinishAction
31+
32+
33+
def reducer(
34+
state: StateType | None,
35+
action: Action,
36+
) -> StateType | CompleteReducerResult[StateType, Action, FinishEvent]:
37+
if state is None:
38+
if isinstance(action, InitAction):
39+
return StateType(value=0)
40+
raise InitializationActionError(action)
41+
42+
if isinstance(action, IncrementAction):
43+
return replace(state, value=state.value + 1)
44+
45+
return state
46+
47+
48+
class StoreType(Store[StateType, Action, FinishEvent]):
49+
@property
50+
def state(self: StoreType) -> StateType | None:
51+
return self._state
52+
53+
54+
@pytest.fixture()
55+
def store() -> Generator[StoreType, None, None]:
56+
store = StoreType(reducer, options=CreateStoreOptions(auto_init=True))
57+
yield store
58+
59+
store.dispatch(FinishAction())
60+
61+
62+
# These tests will timeout if they take a long time to run, indicating a performance
63+
# issue.
64+
65+
66+
def test_simple_dispatch(store: StoreType) -> None:
67+
count = 100000
68+
for _ in range(count):
69+
store.dispatch(IncrementAction())
70+
71+
assert store.state is not None
72+
assert store.state.value == count
73+
74+
75+
def test_dispatch_with_subscriptions(store: StoreType) -> None:
76+
for _ in range(1000):
77+
78+
def callback(_: StateType | None) -> None:
79+
pass
80+
81+
store.subscribe(callback)
82+
83+
count = 500
84+
for _ in range(count):
85+
store.dispatch(IncrementAction())
86+
87+
assert store.state is not None
88+
assert store.state.value == count

0 commit comments

Comments
 (0)