86 lines
2.8 KiB
Python
86 lines
2.8 KiB
Python
"""Shared pytest fixtures for gateway tests.
|
|
|
|
``create_app`` is imported inside the fixture rather than at module scope so
|
|
collecting a subset of the suite does not require every router — and therefore
|
|
every model dependency — to be importable. Suites that do not exercise the
|
|
whole gateway (the conversion tests, for one) can then run on their own, in CI
|
|
images that carry no OCR, OpenCLIP or FAISS weights.
|
|
"""
|
|
|
|
from collections.abc import Iterator
|
|
|
|
import pytest
|
|
from fastapi.testclient import TestClient
|
|
|
|
# The test modules that exercise the document-editing API. Every one of them
|
|
# goes through ``POST /documents``, which needs the native ``pdfengine``
|
|
# pybind11 module; without it the router answers 501 by design and each of
|
|
# these files fails on its first assertion.
|
|
#
|
|
# Sixty-five failures that mean "this environment has no C++ build" are worse
|
|
# than useless: they are indistinguishable from a real regression, so a green
|
|
# suite becomes unattainable and nobody reads the red one. A capability the
|
|
# environment does not have is a *skip*. The engine's own conversion suite
|
|
# (``tests/convert``) is unaffected — it never needed the native module.
|
|
ENGINE_DEPENDENT_MODULES = frozenset(
|
|
{
|
|
"test_compare",
|
|
"test_final_extraction",
|
|
"test_font_regression",
|
|
"test_glyph_metrics",
|
|
"test_inplace_editing",
|
|
"test_layout",
|
|
"test_merge",
|
|
"test_protect",
|
|
"test_replace_text",
|
|
"test_unlock",
|
|
"test_watermark",
|
|
}
|
|
)
|
|
|
|
|
|
def _engine_available() -> bool:
|
|
try:
|
|
from app.services import engine
|
|
except Exception:
|
|
return False
|
|
try:
|
|
return bool(engine.is_available())
|
|
except Exception:
|
|
return False
|
|
|
|
|
|
def pytest_configure(config: pytest.Config) -> None:
|
|
config.addinivalue_line(
|
|
"markers",
|
|
"needs_engine: requires the native pdfengine pybind11 module",
|
|
)
|
|
|
|
|
|
def pytest_collection_modifyitems(config: pytest.Config, items: list[pytest.Item]) -> None:
|
|
"""Skip — do not fail — what this environment cannot run.
|
|
|
|
Marking rather than deleting keeps the count visible: the summary line says
|
|
how many were skipped, so an environment that is *supposed* to have the
|
|
engine shows an obvious, countable anomaly instead of quietly passing less.
|
|
"""
|
|
if _engine_available():
|
|
return
|
|
skip = pytest.mark.skip(
|
|
reason=(
|
|
"native pdfengine module not built " "(app.services.engine.is_available() is False)"
|
|
)
|
|
)
|
|
for item in items:
|
|
module = item.nodeid.split("::")[0].rsplit("/", 1)[-1].removesuffix(".py")
|
|
if module in ENGINE_DEPENDENT_MODULES:
|
|
item.add_marker(skip)
|
|
|
|
|
|
@pytest.fixture()
|
|
def client() -> Iterator[TestClient]:
|
|
from app.main import create_app
|
|
|
|
with TestClient(create_app()) as test_client:
|
|
yield test_client
|