Skip to content

Commit 9bd0855

Browse files
authored
feat(test-tools): Add run_tasks fixture (#85)
1 parent abec78b commit 9bd0855

File tree

7 files changed

+108
-29
lines changed

7 files changed

+108
-29
lines changed

poetry.lock

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ dependencies = [
1919
"requests",
2020
"simplejson (>=3,<4)",
2121
]
22-
optional-dependencies = { test-tools = ["pyfakefs (>=5,<6)"] }
22+
optional-dependencies = { test-tools = [
23+
"pyfakefs (>=5,<6)",
24+
"pytest-django (>=4,<5)",
25+
] }
2326
authors = [
2427
{ name = "Matthew Elwell" },
2528
{ name = "Gagan Trivedi" },

src/common/test_tools/__init__.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
1-
from common.test_tools.types import AssertMetricFixture, SnapshotFixture
1+
from common.test_tools.types import (
2+
AssertMetricFixture,
3+
RunTasksFixture,
4+
SnapshotFixture,
5+
)
26

37
__all__ = (
48
"AssertMetricFixture",
9+
"RunTasksFixture",
510
"SnapshotFixture",
611
)

src/common/test_tools/plugin.py

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
1+
from functools import partial
12
from typing import Generator
23

34
import prometheus_client
45
import pytest
56
from prometheus_client.metrics import MetricWrapperBase
67
from pyfakefs.fake_filesystem import FakeFilesystem
8+
from pytest_django.fixtures import SettingsWrapper
79

8-
from common.test_tools.types import AssertMetricFixture, Snapshot, SnapshotFixture
10+
from common.test_tools.types import (
11+
AssertMetricFixture,
12+
RunTasksFixture,
13+
Snapshot,
14+
SnapshotFixture,
15+
)
16+
from task_processor.task_run_method import TaskRunMethod
917

1018

1119
def pytest_addoption(parser: pytest.Parser) -> None:
@@ -68,6 +76,16 @@ def enterprise_mode(fs: FakeFilesystem) -> Generator[None, None, None]:
6876
is_enterprise.cache_clear()
6977

7078

79+
@pytest.fixture()
80+
def task_processor_mode(settings: SettingsWrapper) -> None:
81+
settings.TASK_PROCESSOR_MODE = True
82+
# The setting is supposed to be set before the metrics module is imported,
83+
# so reload it
84+
from common.prometheus.utils import reload_metrics
85+
86+
reload_metrics("task_processor.metrics")
87+
88+
7189
@pytest.fixture(autouse=True)
7290
def flagsmith_markers_marked(
7391
request: pytest.FixtureRequest,
@@ -77,6 +95,21 @@ def flagsmith_markers_marked(
7795
request.getfixturevalue("saas_mode")
7896
if marker.name == "enterprise_mode":
7997
request.getfixturevalue("enterprise_mode")
98+
if marker.name == "task_processor_mode":
99+
request.getfixturevalue("task_processor_mode")
100+
101+
102+
@pytest.fixture(name="run_tasks")
103+
def run_tasks_impl(
104+
settings: SettingsWrapper,
105+
transactional_db: None,
106+
task_processor_mode: None,
107+
) -> RunTasksFixture:
108+
settings.TASK_RUN_METHOD = TaskRunMethod.TASK_PROCESSOR
109+
110+
from task_processor.processor import run_tasks
111+
112+
return partial(run_tasks, database="default")
80113

81114

82115
@pytest.fixture

src/common/test_tools/types.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
from pathlib import Path
2-
from typing import Protocol
2+
from typing import TYPE_CHECKING, Protocol
33

44
import pytest
55

6+
if TYPE_CHECKING:
7+
from task_processor.models import TaskRun
8+
69

710
class AssertMetricFixture(Protocol):
811
def __call__(
@@ -14,6 +17,13 @@ def __call__(
1417
) -> None: ...
1518

1619

20+
class RunTasksFixture(Protocol):
21+
def __call__(
22+
self,
23+
num_tasks: int,
24+
) -> "list[TaskRun]": ...
25+
26+
1727
class SnapshotFixture(Protocol):
1828
def __call__(self, name: str = "") -> "Snapshot": ...
1929

tests/unit/common/test_tools/test_plugin.py

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1+
from datetime import datetime, timedelta
2+
13
import prometheus_client
24
import pytest
35

4-
from common.test_tools import AssertMetricFixture
6+
from common.test_tools import AssertMetricFixture, RunTasksFixture
57
from common.test_tools.plugin import assert_metric_impl
68
from common.test_tools.utils import edition_printer
9+
from task_processor.decorators import register_task_handler
10+
from task_processor.models import Task
711

812

913
def test_assert_metrics__asserts_expected(
@@ -55,3 +59,44 @@ def test_saas_mode_marker__is_saas_returns_expected() -> None:
5559
def test_enterprise_mode_marker__is_enterprise_returns_expected() -> None:
5660
# When & Then
5761
assert edition_printer() == "enterprise!"
62+
63+
64+
def test_run_tasks__runs_expected_tasks(
65+
run_tasks: RunTasksFixture,
66+
) -> None:
67+
# Given
68+
@register_task_handler()
69+
def my_task() -> None:
70+
return None
71+
72+
my_task.delay()
73+
74+
# When
75+
task_runs = run_tasks(num_tasks=1)
76+
77+
# Then
78+
assert len(task_runs) == 1
79+
assert task_runs[0].task.task_identifier == "test_plugin.my_task"
80+
assert task_runs[0].result == "SUCCESS"
81+
82+
83+
def test_run_tasks__delay_inside_task__runs_expected(
84+
run_tasks: RunTasksFixture,
85+
) -> None:
86+
# Given
87+
@register_task_handler()
88+
def my_task() -> None: ...
89+
90+
@register_task_handler()
91+
def calling_task() -> None:
92+
my_task.delay(delay_until=datetime.now() + timedelta(hours=1))
93+
94+
calling_task.delay()
95+
96+
# When
97+
task_runs = run_tasks(num_tasks=1)
98+
99+
# Then
100+
assert len(task_runs) == 1
101+
assert Task.objects.count() == 2
102+
assert Task.objects.latest("scheduled_for").task_identifier == "test_plugin.my_task"

tests/unit/task_processor/conftest.py

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import pytest
44
from pytest_django.fixtures import SettingsWrapper
55

6-
from common.prometheus.utils import reload_metrics
76
from task_processor.task_registry import RegisteredTask
87

98

@@ -35,22 +34,6 @@ def current_database(
3534
return database
3635

3736

38-
@pytest.fixture()
39-
def task_processor_mode(settings: SettingsWrapper) -> None:
40-
settings.TASK_PROCESSOR_MODE = True
41-
# The setting is supposed to be set before the metrics module is imported,
42-
# so reload it
43-
reload_metrics("task_processor.metrics")
44-
45-
46-
@pytest.fixture(autouse=True)
47-
def task_processor_mode_marked(request: pytest.FixtureRequest) -> None:
48-
for marker in request.node.iter_markers():
49-
if marker.name == "task_processor_mode":
50-
request.getfixturevalue("task_processor_mode")
51-
return
52-
53-
5437
@pytest.fixture(autouse=True)
5538
def task_registry() -> typing.Generator[dict[str, RegisteredTask], None, None]:
5639
from task_processor.task_registry import registered_tasks

0 commit comments

Comments
 (0)