test: add MCP smoke tests over stdio and streamable HTTP, from source and from the built image
ci / gitleaks (push) Successful in 9s
ci / docs-check (push) Failing after 30s
ci / lint (push) Successful in 41s
ci / test-integration (push) Successful in 46s
ci / security (push) Failing after 28s
ci / test-mcp (push) Successful in 1m16s
ci / test-unit (push) Successful in 1m52s
ci / build-and-push (push) Successful in 17s
ci / gitleaks (push) Successful in 9s
ci / docs-check (push) Failing after 30s
ci / lint (push) Successful in 41s
ci / test-integration (push) Successful in 46s
ci / security (push) Failing after 28s
ci / test-mcp (push) Successful in 1m16s
ci / test-unit (push) Successful in 1m52s
ci / build-and-push (push) Successful in 17s
This commit is contained in:
1 parent
cfbf1fb893
commit
5e144772b2
7 files changed
+817
No files matched your search
@@ -0,0 +1,76 @@
|
||||
"""Opt-in fixtures for the MCP smoke tests.
|
||||
|
||||
Tests in this directory are marked ``mcp_smoke`` and skipped unless
|
||||
``AEGIS_INTEGRATION=1``. They reuse the live-Gitea harness from
|
||||
``tests/integration`` (one disposable Gitea per session, admin token with the
|
||||
``all`` scope) and drive the server through a real MCP client over stdio and
|
||||
streamable HTTP, from source and (when ``AEGIS_MCP_IMAGE`` is set) from the
|
||||
built image.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import secrets
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from tests.integration.conftest import ENABLE_ENV, gitea, integration_enabled
|
||||
from tests.integration.harness import GITEA_PORT, GiteaInstance
|
||||
|
||||
__all__ = ["ENABLE_ENV", "gitea"]
|
||||
|
||||
_HERE = Path(__file__).parent.resolve()
|
||||
IMAGE_ENV = "AEGIS_MCP_IMAGE"
|
||||
|
||||
|
||||
def pytest_configure(config: pytest.Config) -> None:
|
||||
"""Register the ``mcp_smoke`` marker (idempotent with pyproject)."""
|
||||
config.addinivalue_line(
|
||||
"markers", "mcp_smoke: MCP client smoke tests, opt-in via AEGIS_INTEGRATION=1"
|
||||
)
|
||||
|
||||
|
||||
def _is_mcp_smoke(item: pytest.Item) -> bool:
|
||||
try:
|
||||
return _HERE in Path(str(item.path)).resolve().parents
|
||||
except (OSError, ValueError): # pragma: no cover - defensive
|
||||
return False
|
||||
|
||||
|
||||
def pytest_collection_modifyitems(config: pytest.Config, items: list[pytest.Item]) -> None:
|
||||
"""Mark and (unless opted in) skip every test under tests/mcp."""
|
||||
selected = [item for item in items if _is_mcp_smoke(item)]
|
||||
skip = pytest.mark.skip(reason=f"MCP smoke tests need {ENABLE_ENV}=1 and Docker")
|
||||
for item in selected:
|
||||
item.add_marker(pytest.mark.mcp_smoke)
|
||||
if not integration_enabled():
|
||||
item.add_marker(skip)
|
||||
if selected and len(selected) == len(items):
|
||||
# A smoke-only run starts the server in subprocesses, so the in-process
|
||||
# coverage gate does not apply.
|
||||
for namespace in (config.option, config.known_args_namespace):
|
||||
if getattr(namespace, "cov_fail_under", None) is not None:
|
||||
namespace.cov_fail_under = 0
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def gitea_internal_url(gitea: GiteaInstance) -> str:
|
||||
"""URL of the Gitea container for other containers on the harness network."""
|
||||
return f"http://{gitea.container}:{GITEA_PORT}"
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def mcp_image() -> str:
|
||||
"""The built image under test; the test is skipped when ``AEGIS_MCP_IMAGE`` is unset."""
|
||||
image = os.environ.get(IMAGE_ENV, "").strip()
|
||||
if not image:
|
||||
pytest.skip(f"{IMAGE_ENV} is not set; image smoke tests need a built image")
|
||||
return image
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def bearer_token() -> str:
|
||||
"""A random 48 character MCP bearer token."""
|
||||
return secrets.token_urlsafe(36)
|
||||
Reference in new issue
Block a user