# Teststrategie ## Doel Tests bewijzen dat VacatureRadar veilig herhaalbaar verzamelt, betrouwbare canonieke data maakt, uitlegbaar scoort en zonder externe services blijft functioneren. De standaardtestset is snel, deterministisch en offline. ## Testpiramide ### Unit Pure functies en begrensde services: - URL-validatie en canonicalisatie; - source policy en denylist; - adapterextractie uit fixtures; - HTML-sanitization; - normalisatie van titel, contract, locatie en datums; - feature-extractie, distance fallback en scoring; - AI-schema/parsing/fallback; - profielgewichten en feedbackgrenzen. Doel: veel kleine tests, geen echte netwerkcall en alleen database wanneer het objectgedrag zelf wordt getest. ### Integratie Meerdere componenten met testdatabase: - raw document → adapter → normalisatie → dedupe → provenance → score; - replay/idempotentie en vacatureversies; - IMAP/e-mailrecording via gesimuleerde berichten; - digest-outbox en mailbackend; - lifecycle en sollicitatiedossier; - Django-views, login, user-scoping en POST-acties; - Celerytasks in eager mode. ### Security Negatieve tests voor trust boundaries: - loopback, private, link-local, encoded/credentialed en onverwachte URL's; - redirecthercontrole; - denylistplatformen; - contenttype/grootte; - XSS/sanitization en onveilige links; - prompt-injectionachtige vacaturetekst; - cross-user objecttoegang; - secret-/payloadlekken in foutpaden waar praktisch testbaar. ### Browser/e2e Gepland in backlogtaak `VR-114`. Gebruik een lokale testserver en seeded data, geen live bron. Minimale flows: 1. aanmelden; 2. dashboard openen; 3. profiel wijzigen en revisie zien; 4. vacature zoeken/openen; 5. interessant/verbergen/gesolliciteerd; 6. sollicitatiedossier bijwerken; 7. bronstatus bekijken; 8. toetsenbord- en basisaccessibilityscan. Browsertests zijn aanvullend; zij vervangen geen service- of autorisatietests. ### Release- en deploymenttests - Dockerfile buildt zonder ontwikkelbestanden/secrets; - container start als niet-rootgebruiker; - migraties en `collectstatic` slagen; - liveness/readiness reageren correct; - Composeconfiguratie parseert; - PostgreSQL/Redisstack verwerkt één fixture en digest; - back-up en restore zijn op een tijdelijke omgeving getest. Deze laag kan in CI of een releasejob draaien zodra een Dockerdaemon beschikbaar is. ## Fixtures Directoryindeling: ```text fixtures/pages/ HTML/JSON-LD fixtures/feeds/ RSS/Atom/sitemaps fixtures/emails/ RFC822-berichten fixtures/golden/ verwachte gestructureerde output ``` Regels: - fictieve werkgevers/personen en `example.*`-domeinen; - alleen het minimum aan vacaturetekst; - geen cookies, tokens, echte Message-ID's of persoonlijke adressen; - bronvariant en doel van fixture in testnaam of korte comment; - grote regressiepayloads waar mogelijk reduceren tot minimale reproducer. ## Netwerkisolatie Geen test mag standaard internet vereisen. Patch `httpx`, DNS-resolutie, IMAP, SMTP en Ollama aan de boundary. Een test die per ongeluk live netwerk gebruikt, is een testfout. Eventuele live smoke-tests krijgen een aparte marker, expliciete environmentflag en draaien nooit in de standaard-CI. ## Dekkingsbeleid `pyproject.toml` vereist minimaal 70% branch-aware totaal. Dekking is een vangnet, geen doel op zich: - fetcher, URL-security, policy, sanitization, authscoping en automatische acties: alle belangrijke negatieve paden; - parsers: iedere ondersteunde variant plus malformed/lege input; - scoring/dedupe: beslisdrempels en tie-breakers; - triviale adminregistratie en migratiecode mogen uit de meting blijven. Verlaag de drempel niet voor een taak. Voeg tests toe of documenteer en verwijder aantoonbaar dode code. ## Testdata en tijd - Gebruik timezone-aware vaste datums of `timezone.now()` relatief binnen de test. - Vermijd assertions die na middernacht lokale tijd flaken. - Randomized/propertytests gebruiken een vaste seed en melden die bij falen. - Volgorde-onafhankelijkheid: iedere test maakt eigen state via fixtures/factories. ## Performance Voor `NFR-007` komt een reproduceerbaar benchmarkscript in `VR-116` met minstens: - 25.000 canonieke vacatures; - meerdere aliassen en scoreruns; - dashboard/list/detailqueries; - importbatch en rescore; - p50/p95, querycount en geheugengebruik. Een performanceclaim wordt alleen in documentatie opgenomen met hardwareprofiel, dataset en meetcommando. ## Uitvoercommando's ```bash uv run pytest tests/unit uv run pytest tests/integration uv run pytest tests/security uv run pytest --cov=apps --cov=config --cov-report=term-missing ./scripts/codex_verify.sh ``` ## Bugworkflow 1. Reproduceer met kleinste betrouwbare fixture/test. 2. Laat de test falen op de huidige code. 3. Herstel bij de laag waar de regel hoort. 4. Draai relevante tests en daarna de volledige gate. 5. Werk threat model/runbook bij wanneer het een security- of operationeel defect was.