|
1 | 1 | import sys |
2 | 2 | import os |
3 | 3 | import time |
| 4 | +import socket |
4 | 5 |
|
5 | 6 | import pytest |
6 | 7 | import logging |
7 | 8 | from testcontainers.compose import DockerCompose |
8 | 9 | from testcontainers.core.docker_client import DockerClient |
| 10 | +from fastapi.testclient import TestClient |
9 | 11 |
|
10 | 12 | from node_normalizer.util import LoggingUtil |
11 | 13 |
|
@@ -49,3 +51,44 @@ def stop(): |
49 | 51 | request.addfinalizer(stop) |
50 | 52 |
|
51 | 53 | return compose, nn_url, callback_url |
| 54 | + |
| 55 | + |
| 56 | +@pytest.fixture(scope="session") |
| 57 | +def integration_client(): |
| 58 | + """ |
| 59 | + Session-scoped fixture for integration tests. |
| 60 | +
|
| 61 | + Requires Redis running on localhost:6379. In CI this is provided by the |
| 62 | + GitHub Actions services.redis block in .github/workflows/test.yml. |
| 63 | + Locally: docker compose -f docker-compose-redis.yml up -d |
| 64 | +
|
| 65 | + The TestClient context manager triggers startup_event(), which establishes |
| 66 | + real Redis connections via redis_config.yaml. All integration tests share |
| 67 | + this single session; tests must be read-only (no writes to Redis). |
| 68 | +
|
| 69 | + Note: startup_event also downloads the Biolink Model YAML from GitHub via |
| 70 | + bmt. This is slow on the first run; bmt caches it in ~/.cache afterward. |
| 71 | + """ |
| 72 | + # Verify Redis is reachable before starting the app; fail fast with a clear |
| 73 | + # message rather than a cryptic connection error from deep inside the app. |
| 74 | + redis_host, redis_port = "127.0.0.1", 6379 |
| 75 | + try: |
| 76 | + with socket.create_connection((redis_host, redis_port), timeout=5): |
| 77 | + pass |
| 78 | + except OSError as exc: |
| 79 | + raise RuntimeError( |
| 80 | + f"Integration tests require Redis on {redis_host}:{redis_port}. " |
| 81 | + "Start it with: docker compose -f docker-compose-redis.yml up -d" |
| 82 | + ) from exc |
| 83 | + |
| 84 | + # PLACEHOLDER: load test data into Redis before starting the app. |
| 85 | + # Fill this in once tests/data/config.json is finalized, e.g.: |
| 86 | + # |
| 87 | + # import asyncio |
| 88 | + # from node_normalizer.loader import NodeLoader |
| 89 | + # loader = NodeLoader("tests/data/config.json") |
| 90 | + # asyncio.run(loader.load(100_000)) |
| 91 | + |
| 92 | + from node_normalizer.server import app |
| 93 | + with TestClient(app) as client: |
| 94 | + yield client |
0 commit comments