feat: add Python integration tests for HTTP endpoints
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
"""Pytest fixture for managing the pipeline-runner server lifecycle during tests."""
|
||||
|
||||
import json
|
||||
import os
|
||||
import shutil
|
||||
import socket
|
||||
import subprocess
|
||||
import tempfile
|
||||
import time
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
def get_free_port():
|
||||
"""Get a free port for the test server."""
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
s.bind(("", 0))
|
||||
port = s.getsockname()[1]
|
||||
s.close()
|
||||
return port
|
||||
|
||||
|
||||
class PipelineServer:
|
||||
"""Manages a pipeline-runner server instance for tests."""
|
||||
|
||||
def __init__(self, port, work_dir, verbose=False):
|
||||
self.port = port
|
||||
self.work_dir = work_dir
|
||||
self.verbose = verbose
|
||||
|
||||
test_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
project_root = os.path.dirname(test_dir)
|
||||
self.bin_path = os.path.join(project_root, "build", "pipeline-runner")
|
||||
|
||||
config = {
|
||||
"port": port,
|
||||
"pipelines_dir": os.path.join(work_dir, "pipelines") + "/",
|
||||
"logs_dir": os.path.join(work_dir, "logs") + "/",
|
||||
}
|
||||
self.config_path = os.path.join(work_dir, "pipeline-runner.conf")
|
||||
with open(self.config_path, "w") as f:
|
||||
json.dump(config, f)
|
||||
|
||||
self.process = None
|
||||
|
||||
@property
|
||||
def base_url(self):
|
||||
return f"http://localhost:{self.port}"
|
||||
|
||||
def start(self, timeout=30):
|
||||
"""Start the server and wait until it responds."""
|
||||
self.process = subprocess.Popen(
|
||||
[self.bin_path, self.config_path],
|
||||
cwd=self.work_dir,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
)
|
||||
|
||||
deadline = time.time() + timeout
|
||||
while time.time() < deadline:
|
||||
try:
|
||||
resp = __import__("requests").get(
|
||||
f"{self.base_url}/api/pipelines", timeout=1
|
||||
)
|
||||
if resp.status_code == 200:
|
||||
return True
|
||||
except Exception:
|
||||
pass
|
||||
time.sleep(0.3)
|
||||
|
||||
return False
|
||||
|
||||
def stop(self):
|
||||
"""Stop the server."""
|
||||
if self.process:
|
||||
self.process.terminate()
|
||||
try:
|
||||
self.process.wait(timeout=10)
|
||||
except subprocess.TimeoutExpired:
|
||||
self.process.kill()
|
||||
self.process.wait(timeout=5)
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def pipeline_server():
|
||||
"""Session-scoped fixture that builds, starts, and stops the pipeline-runner server."""
|
||||
project_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
build_script = os.path.join(project_dir, "build.sh")
|
||||
|
||||
subprocess.check_call([build_script, "--fake"], cwd=project_dir)
|
||||
|
||||
work_dir = tempfile.mkdtemp(prefix="pipeline-test-")
|
||||
port = get_free_port()
|
||||
|
||||
server = PipelineServer(port, work_dir)
|
||||
if not server.start():
|
||||
pytest.fail("Could not start pipeline-runner server")
|
||||
|
||||
yield server
|
||||
|
||||
server.stop()
|
||||
shutil.rmtree(work_dir, ignore_errors=True)
|
||||
Reference in New Issue
Block a user