Skip to content

Commit

Permalink
Added documentation to the smoke tests infra (#8970)
Browse files Browse the repository at this point in the history
  • Loading branch information
Nusnus committed Apr 17, 2024
1 parent 3e018cb commit 54df3e9
Show file tree
Hide file tree
Showing 10 changed files with 94 additions and 9 deletions.
21 changes: 19 additions & 2 deletions t/smoke/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,20 @@ class SuiteOperations(
WorkerKill,
WorkerRestart,
):
pass
"""Optional operations that can be performed with different methods,
shared across the smoke tests suite.
Example Usage:
>>> class test_mysuite(SuiteOperations):
>>> def test_something(self):
>>> self.prepare_worker_with_conditions()
>>> assert condition are met
"""


@pytest.fixture
def default_worker_tasks(default_worker_tasks: set) -> set:
"""Use all of the integration and smoke suites tasks in the smoke tests workers."""
from t.integration import tasks as integration_tests_tasks
from t.smoke import tasks as smoke_tests_tasks

Expand All @@ -31,6 +40,10 @@ def default_worker_tasks(default_worker_tasks: set) -> set:
return default_worker_tasks


# When using integration tests tasks that requires a Redis instance,
# we use pytest-celery to raise a dedicated Redis container for the smoke tests suite that is configured
# to be used by the integration tests tasks.

redis_image = fetch(repository=REDIS_IMAGE)
redis_test_container_network = network(scope="session")
redis_test_container: RedisContainer = container(
Expand All @@ -44,6 +57,10 @@ def default_worker_tasks(default_worker_tasks: set) -> set:
)


@pytest.fixture(scope="session", autouse=True)
@pytest.fixture(
scope="session",
autouse=True, # Ensure the configuration is applied automatically
)
def set_redis_test_container(redis_test_container: RedisContainer):
"""Configure the Redis test container to be used by the integration tests tasks."""
os.environ["REDIS_PORT"] = str(redis_test_container.port)
10 changes: 10 additions & 0 deletions t/smoke/operations/task_termination.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@


class TaskTermination:
"""Terminates a task in different ways."""
class Method(Enum):
SIGKILL = auto()
SYSTEM_EXIT = auto()
Expand All @@ -22,6 +23,15 @@ def apply_self_termination_task(
worker: CeleryTestWorker,
method: TaskTermination.Method,
) -> AsyncResult:
"""Apply a task that will terminate itself.
Args:
worker (CeleryTestWorker): Take the queue of this worker.
method (TaskTermination.Method): The method to terminate the task.
Returns:
AsyncResult: The result of applying the task.
"""
try:
self_termination_sig: Signature = {
TaskTermination.Method.SIGKILL: self_termination_sigkill.si(),
Expand Down
10 changes: 9 additions & 1 deletion t/smoke/operations/worker_kill.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@


class WorkerKill:
"""Kills a worker in different ways."""
class Method(Enum):
DOCKER_KILL = auto()
CONTROL_SHUTDOWN = auto()
Expand All @@ -17,7 +18,14 @@ def kill_worker(
worker: CeleryTestWorker,
method: WorkerKill.Method,
assertion: bool = True,
):
) -> None:
"""Kill a Celery worker.
Args:
worker (CeleryTestWorker): Worker to kill.
method (WorkerKill.Method): The method to kill the worker.
assertion (bool, optional): Whether to assert the worker state after kill. Defaults to True.
"""
if method == WorkerKill.Method.DOCKER_KILL:
worker.kill()

Expand Down
10 changes: 9 additions & 1 deletion t/smoke/operations/worker_restart.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@


class WorkerRestart:
"""Restarts a worker in different ways."""
class Method(Enum):
POOL_RESTART = auto()
DOCKER_RESTART_GRACEFULLY = auto()
Expand All @@ -16,7 +17,14 @@ def restart_worker(
worker: CeleryTestWorker,
method: WorkerRestart.Method,
assertion: bool = True,
):
) -> None:
"""Restart a Celery worker.
Args:
worker (CeleryTestWorker): Worker to restart.
method (WorkerRestart.Method): The method to restart the worker.
assertion (bool, optional): Whether to assert the worker state after restart. Defaults to True.
"""
if method == WorkerRestart.Method.POOL_RESTART:
worker.app.control.pool_restart()
worker.container.reload()
Expand Down
12 changes: 7 additions & 5 deletions t/smoke/signals.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,28 @@
"""Signal Handlers for the smoke test."""

from celery.signals import worker_init, worker_process_init, worker_process_shutdown, worker_ready, worker_shutdown


@worker_init.connect
def worker_init_handler(sender, **kwargs): # type: ignore
def worker_init_handler(sender, **kwargs):
print("worker_init_handler")


@worker_process_init.connect
def worker_process_init_handler(sender, **kwargs): # type: ignore
def worker_process_init_handler(sender, **kwargs):
print("worker_process_init_handler")


@worker_process_shutdown.connect
def worker_process_shutdown_handler(sender, pid, exitcode, **kwargs): # type: ignore
def worker_process_shutdown_handler(sender, pid, exitcode, **kwargs):
print("worker_process_shutdown_handler")


@worker_ready.connect
def worker_ready_handler(sender, **kwargs): # type: ignore
def worker_ready_handler(sender, **kwargs):
print("worker_ready_handler")


@worker_shutdown.connect
def worker_shutdown_handler(sender, **kwargs): # type: ignore
def worker_shutdown_handler(sender, **kwargs):
print("worker_shutdown_handler")
2 changes: 2 additions & 0 deletions t/smoke/tasks.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""Smoke tests tasks."""

from __future__ import annotations

import os
Expand Down
6 changes: 6 additions & 0 deletions t/smoke/workers/alt.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,14 @@


class AltSmokeWorkerContainer(SmokeWorkerContainer):
"""Alternative worker with different name, but same configurations."""

@classmethod
def worker_name(cls) -> str:
return "alt_smoke_tests_worker"


# Build the image like the dev worker
celery_alt_dev_worker_image = build(
path=".",
dockerfile="t/smoke/workers/docker/dev",
Expand All @@ -24,6 +27,7 @@ def worker_name(cls) -> str:
)


# Define container settings like the dev worker
alt_dev_worker_container = container(
image="{celery_alt_dev_worker_image.id}",
environment=fxtr("default_worker_env"),
Expand All @@ -39,6 +43,7 @@ def worker_name(cls) -> str:
},
wrapper_class=AltSmokeWorkerContainer,
timeout=defaults.DEFAULT_WORKER_CONTAINER_TIMEOUT,
command=AltSmokeWorkerContainer.command(),
)


Expand All @@ -47,6 +52,7 @@ def celery_alt_dev_worker(
alt_dev_worker_container: AltSmokeWorkerContainer,
celery_setup_app: Celery,
) -> CeleryTestWorker:
"""Creates a pytest-celery worker node from the worker container."""
worker = CeleryTestWorker(alt_dev_worker_container, app=celery_setup_app)
yield worker
worker.teardown()
17 changes: 17 additions & 0 deletions t/smoke/workers/dev.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@


class SmokeWorkerContainer(CeleryWorkerContainer):
"""Defines the configurations for the smoke tests worker container.
This worker will install Celery from the current source code.
"""

@property
def client(self) -> Any:
return self
Expand All @@ -30,6 +35,7 @@ def worker_queue(cls) -> str:
return "smoke_tests_queue"


# Build the image from the current source code
celery_dev_worker_image = build(
path=".",
dockerfile="t/smoke/workers/docker/dev",
Expand All @@ -38,6 +44,7 @@ def worker_queue(cls) -> str:
)


# Define container settings
default_worker_container = container(
image="{celery_dev_worker_image.id}",
ports=fxtr("default_worker_ports"),
Expand All @@ -60,9 +67,19 @@ def worker_queue(cls) -> str:

@pytest.fixture
def default_worker_container_cls() -> Type[CeleryWorkerContainer]:
"""Replace the default pytest-celery worker container with the smoke tests worker container.
This will allow the default fixtures of pytest-celery to use the custom worker
configuration using the vendor class.
"""
return SmokeWorkerContainer


@pytest.fixture(scope="session")
def default_worker_container_session_cls() -> Type[CeleryWorkerContainer]:
"""Replace the default pytest-celery worker container with the smoke tests worker container.
This will allow the default fixtures of pytest-celery to use the custom worker
configuration using the vendor class.
"""
return SmokeWorkerContainer
9 changes: 9 additions & 0 deletions t/smoke/workers/latest.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@


class CeleryLatestWorkerContainer(CeleryWorkerContainer):
"""Defines the configurations for a Celery worker container.
This worker will install the latest version of Celery from PyPI.
"""

@property
def client(self) -> Any:
return self
Expand All @@ -25,6 +30,7 @@ def worker_queue(cls) -> str:
return "celery_latest_tests_queue"


# Build the image from the PyPI Dockerfile
celery_latest_worker_image = build(
path=".",
dockerfile="t/smoke/workers/docker/pypi",
Expand All @@ -33,13 +39,15 @@ def worker_queue(cls) -> str:
)


# Define container settings
celery_latest_worker_container = container(
image="{celery_latest_worker_image.id}",
environment=fxtr("default_worker_env"),
network="{default_pytest_celery_network.name}",
volumes={"{default_worker_volume.name}": defaults.DEFAULT_WORKER_VOLUME},
wrapper_class=CeleryLatestWorkerContainer,
timeout=defaults.DEFAULT_WORKER_CONTAINER_TIMEOUT,
command=CeleryLatestWorkerContainer.command(),
)


Expand All @@ -48,6 +56,7 @@ def celery_latest_worker(
celery_latest_worker_container: CeleryLatestWorkerContainer,
celery_setup_app: Celery,
) -> CeleryTestWorker:
"""Creates a pytest-celery worker node from the worker container."""
worker = CeleryTestWorker(celery_latest_worker_container, app=celery_setup_app)
yield worker
worker.teardown()
6 changes: 6 additions & 0 deletions t/smoke/workers/other.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@


class OtherSmokeWorkerContainer(SmokeWorkerContainer):
"""Alternative worker with different name and queue, but same configurations for the rest."""

@classmethod
def worker_name(cls) -> str:
return "other_smoke_tests_worker"
Expand All @@ -20,6 +22,7 @@ def worker_queue(cls) -> str:
return "other_smoke_tests_queue"


# Build the image like the dev worker
celery_other_dev_worker_image = build(
path=".",
dockerfile="t/smoke/workers/docker/dev",
Expand All @@ -28,6 +31,7 @@ def worker_queue(cls) -> str:
)


# Define container settings like the dev worker
other_dev_worker_container = container(
image="{celery_other_dev_worker_image.id}",
environment=fxtr("default_worker_env"),
Expand All @@ -43,6 +47,7 @@ def worker_queue(cls) -> str:
},
wrapper_class=OtherSmokeWorkerContainer,
timeout=defaults.DEFAULT_WORKER_CONTAINER_TIMEOUT,
command=OtherSmokeWorkerContainer.command(),
)


Expand All @@ -51,6 +56,7 @@ def celery_other_dev_worker(
other_dev_worker_container: OtherSmokeWorkerContainer,
celery_setup_app: Celery,
) -> CeleryTestWorker:
"""Creates a pytest-celery worker node from the worker container."""
worker = CeleryTestWorker(other_dev_worker_container, app=celery_setup_app)
yield worker
worker.teardown()

0 comments on commit 54df3e9

Please sign in to comment.