diff --git a/scripts/get-test-instance-id.sh b/scripts/get-test-instance-id.sh new file mode 100755 index 0000000..911b8bc --- /dev/null +++ b/scripts/get-test-instance-id.sh @@ -0,0 +1,7 @@ +#!/bin/bash +# scripts/get-test-instance-id.sh +# Generate a unique instance ID from git branch for parallel test isolation + +BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown") +# Sanitize: replace non-alphanumeric with dash, limit length +echo "$BRANCH" | sed 's/[^a-zA-Z0-9]/-/g' | cut -c1-20 diff --git a/scripts/run-integration-tests.sh b/scripts/run-integration-tests.sh new file mode 100755 index 0000000..82cc3b2 --- /dev/null +++ b/scripts/run-integration-tests.sh @@ -0,0 +1,39 @@ +#!/bin/bash +# scripts/run-integration-tests.sh +# Run integration tests with branch isolation and dynamic port discovery +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" + +# Get branch-based instance ID +TEST_INSTANCE_ID=$("$SCRIPT_DIR/get-test-instance-id.sh") +export TEST_INSTANCE_ID + +echo "Test instance ID: $TEST_INSTANCE_ID" + +# Start containers +cd "$PROJECT_ROOT/deploy/test" +docker compose up -d --build --wait + +# Discover dynamic ports +GRIST_MCP_PORT=$(docker compose port grist-mcp 3000 | cut -d: -f2) +MOCK_GRIST_PORT=$(docker compose port mock-grist 8484 | cut -d: -f2) + +echo "grist-mcp available at: http://localhost:$GRIST_MCP_PORT" +echo "mock-grist available at: http://localhost:$MOCK_GRIST_PORT" + +# Export for tests +export GRIST_MCP_URL="http://localhost:$GRIST_MCP_PORT" +export MOCK_GRIST_URL="http://localhost:$MOCK_GRIST_PORT" + +# Run tests +cd "$PROJECT_ROOT" +TEST_EXIT=0 +uv run pytest tests/integration/ -v || TEST_EXIT=$? + +# Cleanup +cd "$PROJECT_ROOT/deploy/test" +docker compose down -v + +exit $TEST_EXIT diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 5560e55..4e1ff1f 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -1,13 +1,14 @@ """Fixtures for integration tests.""" +import os import time import httpx import pytest -GRIST_MCP_URL = "http://localhost:3000" -MOCK_GRIST_URL = "http://localhost:8484" +GRIST_MCP_URL = os.environ.get("GRIST_MCP_URL", "http://localhost:3000") +MOCK_GRIST_URL = os.environ.get("MOCK_GRIST_URL", "http://localhost:8484") MAX_WAIT_SECONDS = 30 diff --git a/tests/integration/test_mcp_protocol.py b/tests/integration/test_mcp_protocol.py index 0471b90..0e0d237 100644 --- a/tests/integration/test_mcp_protocol.py +++ b/tests/integration/test_mcp_protocol.py @@ -1,5 +1,6 @@ """Test MCP protocol compliance over SSE transport.""" +import os from contextlib import asynccontextmanager import pytest @@ -7,7 +8,7 @@ from mcp import ClientSession from mcp.client.sse import sse_client -GRIST_MCP_URL = "http://localhost:3000" +GRIST_MCP_URL = os.environ.get("GRIST_MCP_URL", "http://localhost:3000") @asynccontextmanager diff --git a/tests/integration/test_tools_integration.py b/tests/integration/test_tools_integration.py index 2f3e6ad..e7d7ff2 100644 --- a/tests/integration/test_tools_integration.py +++ b/tests/integration/test_tools_integration.py @@ -1,6 +1,7 @@ """Test tool calls through MCP client to verify Grist API interactions.""" import json +import os from contextlib import asynccontextmanager import httpx @@ -9,8 +10,8 @@ from mcp import ClientSession from mcp.client.sse import sse_client -GRIST_MCP_URL = "http://localhost:3000" -MOCK_GRIST_URL = "http://localhost:8484" +GRIST_MCP_URL = os.environ.get("GRIST_MCP_URL", "http://localhost:3000") +MOCK_GRIST_URL = os.environ.get("MOCK_GRIST_URL", "http://localhost:8484") @asynccontextmanager