diff options
| author | TheSiahxyz <164138827+TheSiahxyz@users.noreply.github.com> | 2026-04-01 16:09:06 +0900 |
|---|---|---|
| committer | TheSiahxyz <164138827+TheSiahxyz@users.noreply.github.com> | 2026-04-01 16:09:06 +0900 |
| commit | ec792a3d379c911165038d8da5b339df6ca3fccd (patch) | |
| tree | 324361089617b18110265efd10d174bbb0990b9f /shared/tests | |
| parent | e1bf24b2a639ba21361ae408ee6c1eebe37801aa (diff) | |
feat(shared): add health checks and Prometheus metrics
Diffstat (limited to 'shared/tests')
| -rw-r--r-- | shared/tests/test_healthcheck.py | 88 | ||||
| -rw-r--r-- | shared/tests/test_metrics.py | 51 |
2 files changed, 139 insertions, 0 deletions
diff --git a/shared/tests/test_healthcheck.py b/shared/tests/test_healthcheck.py new file mode 100644 index 0000000..1af86b1 --- /dev/null +++ b/shared/tests/test_healthcheck.py @@ -0,0 +1,88 @@ +"""Tests for health check server.""" +import pytest +import asyncio +from prometheus_client import CollectorRegistry + + +@pytest.fixture +def registry(): + return CollectorRegistry() + + +def make_server(service_name="test-service", port=8080, registry=None): + from shared.healthcheck import HealthCheckServer + return HealthCheckServer(service_name, port=port, registry=registry) + + +def test_init_defaults(registry): + """HealthCheckServer initialises with service name and port.""" + server = make_server("my-service", registry=registry) + assert server.service_name == "my-service" + assert server.port == 8080 + assert server._checks == {} + + +def test_register_check(registry): + """register_check stores an async callable.""" + server = make_server(registry=registry) + + async def check_redis(): + return True + + server.register_check("redis", check_redis) + assert "redis" in server._checks + assert server._checks["redis"] is check_redis + + +@pytest.mark.asyncio +async def test_run_checks_all_pass(registry): + """run_checks returns 'ok' when all checks pass.""" + server = make_server(registry=registry) + + async def ok_check(): + return True + + server.register_check("db", ok_check) + server.register_check("redis", ok_check) + + result = await server.run_checks() + assert result["status"] == "ok" + assert result["service"] == "test-service" + assert "uptime_seconds" in result + assert result["checks"]["db"] == "ok" + assert result["checks"]["redis"] == "ok" + + +@pytest.mark.asyncio +async def test_run_checks_one_fails(registry): + """run_checks returns 'degraded' when a check fails.""" + server = make_server(registry=registry) + + async def ok_check(): + return True + + async def bad_check(): + raise ConnectionError("down") + + server.register_check("db", ok_check) + server.register_check("redis", bad_check) + + result = await server.run_checks() + assert result["status"] == "degraded" + assert result["checks"]["db"] == "ok" + assert "fail" in result["checks"]["redis"] + + +@pytest.mark.asyncio +async def test_run_checks_false_is_fail(registry): + """run_checks treats False return as failure.""" + server = make_server(registry=registry) + + async def false_check(): + return False + + server.register_check("cache", false_check) + + result = await server.run_checks() + assert result["status"] == "degraded" + assert result["checks"]["cache"] == "fail" diff --git a/shared/tests/test_metrics.py b/shared/tests/test_metrics.py new file mode 100644 index 0000000..079f01c --- /dev/null +++ b/shared/tests/test_metrics.py @@ -0,0 +1,51 @@ +"""Tests for Prometheus metrics utilities.""" +import pytest +from prometheus_client import CollectorRegistry + + +def make_metrics(service_name="test-service", registry=None): + from shared.metrics import ServiceMetrics + return ServiceMetrics(service_name, registry=registry) + + +def test_metrics_creates_with_prefix(): + """ServiceMetrics stores sanitized service name prefix.""" + registry = CollectorRegistry() + m = make_metrics("my-service", registry=registry) + assert m.service_name == "my_service" + + +def test_errors_total_increment(): + """errors_total counter can be incremented with labels.""" + registry = CollectorRegistry() + m = make_metrics("test-svc", registry=registry) + m.errors_total.labels(service="test_svc", error_type="timeout").inc() + assert m.errors_total.labels(service="test_svc", error_type="timeout")._value.get() == 1.0 + + +def test_events_processed_increment(): + """events_processed counter can be incremented with labels.""" + registry = CollectorRegistry() + m = make_metrics("test-svc", registry=registry) + m.events_processed.labels(service="test_svc", event_type="candle").inc(5) + assert m.events_processed.labels(service="test_svc", event_type="candle")._value.get() == 5.0 + + +def test_processing_seconds_observe(): + """processing_seconds histogram can observe values.""" + registry = CollectorRegistry() + m = make_metrics("test-svc", registry=registry) + m.processing_seconds.labels(service="test_svc").observe(0.5) + m.processing_seconds.labels(service="test_svc").observe(1.5) + # Sum should be 2.0 + assert m.processing_seconds.labels(service="test_svc")._sum.get() == 2.0 + + +def test_service_up_gauge(): + """service_up gauge can be set.""" + registry = CollectorRegistry() + m = make_metrics("test-svc", registry=registry) + m.service_up.labels(service="test_svc").set(1) + assert m.service_up.labels(service="test_svc")._value.get() == 1.0 + m.service_up.labels(service="test_svc").set(0) + assert m.service_up.labels(service="test_svc")._value.get() == 0.0 |
