- Pyproject.toml mit FastAPI, Pydantic v2, SQLAlchemy, httpx, asyncio, BeautifulSoup4, selectolax, trafilatura, uvicorn, pytest-asyncio - Multi-stage Dockerfile (Python 3.12-slim, Non-Root-User nsct) - docker-compose.yml (nsct-api + postgres + optional searxng) - .env.example mit allen Config-Parametern - Config-System: AppSettings mit LLMConfig, VisionConfig, AudioConfig, DatabaseConfig — komplett aus Environment, keine Hardcodes - Strukturiertes Logging mit research_id/llm_request_id Tracking - Pydantic v2 Schemas: SearchQuery, Source, Claim, EvidenceRelation, CitationEdge, ResearchReport - SQLAlchemy 2.0 Declarative Models + async Engine Factory - SSRF-Schutz: URL-Validation, IP-Blocklist (RFC1918, Cloud Metadata, file://, ftp://) - Provider-Interfaces: LLMProvider, VisionProvider, AudioProvider, SearchProvider, ContentFetcher als ABCs - Health-Endpoints: /health, /ready (LLM-Connect-Test), /providers - FastAPI App mit CORS, lifespan (LLM Pre-Flight) - CLI-Stub mit Entry-Points: nsct, nsct-core, nsct-api - 6 Test-Cases: /health, /ready, /providers + No-Secrets-Test - Vollständige Dokumentation: README, ARCHITECTURE, SECURITY, METHODOLOGY, API, DEPLOYMENT - .gitignore (Python, Docker, IDE, .env)
50 lines
1.7 KiB
Python
50 lines
1.7 KiB
Python
"""pytest fixtures for NSCT tests."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
from typing import AsyncGenerator
|
|
|
|
import pytest
|
|
import pytest_asyncio
|
|
from fastapi.testclient import TestClient
|
|
from httpx import AsyncClient
|
|
|
|
from nsct.api.main import create_app
|
|
from nsct.config import AppSettings
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def app() -> AppSettings:
|
|
"""Minimal AppSettings for test environment."""
|
|
return AppSettings.from_env()
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def client(app: AppSettings):
|
|
"""Synchronous test client for the FastAPI app."""
|
|
fastapi_app = create_app()
|
|
with TestClient(fastapi_app) as c:
|
|
yield c
|
|
|
|
|
|
@pytest_asyncio.fixture(scope="function")
|
|
async def async_client(app: AppSettings) -> AsyncGenerator[AsyncClient, None]:
|
|
"""Async test client for the FastAPI app."""
|
|
fastapi_app = create_app()
|
|
async with AsyncClient(app=fastapi_app, base_url="http://test") as ac:
|
|
yield ac
|
|
|
|
|
|
@pytest.fixture(scope="function")
|
|
def clean_env(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
"""Ensure environment has the minimum required vars for AppSettings."""
|
|
monkeypatch.setenv("NSCT_LLM_BASE_URL", "http://localhost:8030/openai/v1")
|
|
monkeypatch.setenv("NSCT_LLM_MODEL", "test-model")
|
|
monkeypatch.setenv("NSCT_LLM_MAX_CONCURRENCY", "1")
|
|
monkeypatch.setenv("NSCT_VISION_BASE_URL", "http://localhost:8030/openai/visual/v1")
|
|
monkeypatch.setenv("NSCT_VISION_MODEL", "test-model")
|
|
monkeypatch.setenv("NSCT_AUDIO_BASE_URL", "http://localhost:8030/hermes-audio")
|
|
monkeypatch.setenv("NSCT_AUDIO_MODEL", "default")
|
|
monkeypatch.setenv("NSCT_DB_URL", "sqlite+aiosqlite:///:memory:")
|
|
monkeypatch.setenv("NSCT_DEBUG", "false") |