Skip to content

Commit f791921

Browse files
authored
Feature: Support for dynamic worker args (#203)
* Bugfix: RedisContainer.command() was skipping the fixtures layer * Feature: New worker fixture "default_worker_command"
1 parent 66ceab8 commit f791921

File tree

12 files changed

+96
-6
lines changed

12 files changed

+96
-6
lines changed

docs/userguide/examples/django.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ and `container <https://github.com/Jc2k/pytest-docker-tools?tab=readme-ov-file#c
144144
},
145145
wrapper_class=DjangoWorkerContainer,
146146
timeout=defaults.DEFAULT_WORKER_CONTAINER_TIMEOUT,
147+
command=fxtr("default_worker_command"),
147148
)
148149
149150
In this case, we also mount the project directory to ``/src`` in the container, so that we can install the project

examples/django/tests/conftest.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ def worker_queue(cls) -> str:
5858
},
5959
wrapper_class=DjangoWorkerContainer,
6060
timeout=defaults.DEFAULT_WORKER_CONTAINER_TIMEOUT,
61+
command=fxtr("default_worker_command"),
6162
)
6263

6364

src/pytest_celery/api/container.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,6 @@ def command(cls, *args: str) -> list[str]:
7171
the first element, followed by the command-line arguments.
7272
"""
7373

74-
# To be used with pytest_docker_tools.container using the command
75-
# kwarg with the class method as value
76-
# e.g. command=MyContainer.command()
7774
raise NotImplementedError("CeleryTestContainer.command")
7875

7976
def teardown(self) -> None:

src/pytest_celery/vendors/redis/backend/fixtures.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,23 @@ def default_redis_backend_cls() -> type[RedisContainer]:
5050
network="{default_pytest_celery_network.name}",
5151
wrapper_class=RedisContainer,
5252
timeout=REDIS_CONTAINER_TIMEOUT,
53-
command=RedisContainer.command("--maxclients", "100000"),
53+
command=fxtr("default_redis_backend_command"),
5454
)
5555

5656

57+
@pytest.fixture
58+
def default_redis_backend_command(default_redis_backend_cls: type[RedisContainer]) -> list[str]:
59+
"""Command to run the container.
60+
61+
Args:
62+
default_redis_backend_cls (type[RedisContainer]): See also: :ref:`vendor-class`.
63+
64+
Returns:
65+
list[str]: Docker CMD instruction.
66+
"""
67+
return default_redis_backend_cls.command("--maxclients", "100000")
68+
69+
5770
@pytest.fixture
5871
def default_redis_backend_env(default_redis_backend_cls: type[RedisContainer]) -> dict:
5972
"""Environment variables for this vendor.

src/pytest_celery/vendors/redis/broker/fixtures.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,23 @@ def default_redis_broker_cls() -> type[RedisContainer]:
5050
network="{default_pytest_celery_network.name}",
5151
wrapper_class=RedisContainer,
5252
timeout=REDIS_CONTAINER_TIMEOUT,
53-
command=RedisContainer.command("--maxclients", "100000"),
53+
command=fxtr("default_redis_broker_command"),
5454
)
5555

5656

57+
@pytest.fixture
58+
def default_redis_broker_command(default_redis_broker_cls: type[RedisContainer]) -> list[str]:
59+
"""Command to run the container.
60+
61+
Args:
62+
default_redis_broker_cls (type[RedisContainer]): See also: :ref:`vendor-class`.
63+
64+
Returns:
65+
list[str]: Docker CMD instruction.
66+
"""
67+
return default_redis_broker_cls.command("--maxclients", "100000")
68+
69+
5770
@pytest.fixture
5871
def default_redis_broker_env(default_redis_broker_cls: type[RedisContainer]) -> dict:
5972
"""Environment variables for this vendor.

src/pytest_celery/vendors/worker/container.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,22 @@ class CeleryWorkerContainer(CeleryTestContainer):
3232
dependencies of your project.
3333
"""
3434

35+
@classmethod
36+
def command(cls, *args: str) -> list[str]:
37+
args = args or tuple()
38+
return [
39+
"celery",
40+
"-A",
41+
"app",
42+
"worker",
43+
f"--loglevel={cls.log_level()}",
44+
"-n",
45+
f"{cls.worker_name()}@%h",
46+
"-Q",
47+
f"{cls.worker_queue()}",
48+
*args,
49+
]
50+
3551
def _wait_port(self, port: str) -> int:
3652
# Not needed for worker container
3753
raise NotImplementedError

src/pytest_celery/vendors/worker/fixtures.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ def default_worker_container_session_cls() -> type[CeleryWorkerContainer]:
9191
volumes={"{default_worker_volume.name}": DEFAULT_WORKER_VOLUME},
9292
wrapper_class=CeleryWorkerContainer,
9393
timeout=DEFAULT_WORKER_CONTAINER_TIMEOUT,
94+
command=fxtr("default_worker_command"),
9495
)
9596

9697
celery_base_worker_image = build(
@@ -161,6 +162,19 @@ def default_worker_celery_worker_queue(default_worker_container_session_cls: typ
161162
return default_worker_container_session_cls.worker_queue()
162163

163164

165+
@pytest.fixture
166+
def default_worker_command(default_worker_container_cls: type[CeleryWorkerContainer]) -> list[str]:
167+
"""Command to run the container.
168+
169+
Args:
170+
default_worker_container_cls (type[CeleryWorkerContainer]): See also: :ref:`vendor-class`.
171+
172+
Returns:
173+
list[str]: Docker CMD instruction.
174+
"""
175+
return default_worker_container_cls.command()
176+
177+
164178
@pytest.fixture
165179
def default_worker_env(
166180
default_worker_container_cls: type[CeleryWorkerContainer],
@@ -201,7 +215,7 @@ def default_worker_initial_content(
201215
202216
.. note::
203217
204-
Move volumes may be added additionally.
218+
More volumes may be added additionally.
205219
206220
Args:
207221
default_worker_container_cls (type[CeleryWorkerContainer]): See also: :ref:`vendor-class`.

tests/integration/api/custom_setup/conftest.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ def default_worker_container_session_cls() -> type[CeleryWorkerContainer]:
110110
volumes={"{default_worker_volume.name}": DEFAULT_WORKER_VOLUME},
111111
wrapper_class=Celery5WorkerContainer,
112112
timeout=DEFAULT_WORKER_CONTAINER_TIMEOUT,
113+
command=fxtr("default_worker_command"),
113114
)
114115

115116

tests/integration/conftest.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,5 @@ def default_worker_container_session_cls() -> type[CeleryWorkerContainer]:
5656
volumes={"{default_worker_volume.name}": DEFAULT_WORKER_VOLUME},
5757
wrapper_class=IntegrationWorkerContainer,
5858
timeout=DEFAULT_WORKER_CONTAINER_TIMEOUT,
59+
command=fxtr("default_worker_command"),
5960
)

tests/integration/vendors/test_worker.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,14 @@ def default_worker_app_module(self, request: pytest.FixtureRequest) -> ModuleTyp
5050
def test_replacing_app_module(self, container: CeleryWorkerContainer, default_worker_app_module: ModuleType):
5151
assert container.app_module() == default_worker_app_module
5252

53+
class test_replacing_command:
54+
@pytest.fixture
55+
def default_worker_command(self, default_worker_command: list[str]) -> list[str]:
56+
return [*default_worker_command, "--pool", "solo"]
57+
58+
def test_replacing_command(self, container: CeleryWorkerContainer):
59+
assert container.logs().count("solo") == 1
60+
5361

5462
class test_base_test_worker:
5563
def test_config(self, celery_setup_worker: CeleryTestWorker):

0 commit comments

Comments
 (0)