Aller au contenu

Lancer et écrire les tests

En bref

  • piighost a plus de mille tests automatiques. Ils tournent en quelques secondes sans télécharger de modèle d'IA.
  • Les tests qui chargent de vrais modèles sont à part. Ils tournent chaque nuit sur GitHub.
  • Avant toute fusion, un contrôle bloquant vérifie la mise en forme, les types, la sécurité du code et la documentation.
  • Une partie des tests n'est lancée par aucune tâche automatique, faute des bibliothèques nécessaires. Voir Ce qui ne tourne nulle part en CI.

Les termes sont définis dans le glossaire.

Lancer les tests

Vous voulez…Commande
Installer l'environnement de développementuv sync
Lancer toute la suite rapideuv run pytest
Lancer un test précisuv run pytest tests/pipeline/test_pipeline.py -k "nom_du_test"
Lancer les tests qui chargent des modèlesuv run pytest -m integration
Corriger la mise en formemake format
Passer le contrôle bloquantmake lint

addopts exclut le marqueur integration par défaut et désactive les extensions anyio et langsmith_plugin (pyproject.toml:166). Avec asyncio_mode = "auto", un test async def n'a pas besoin de décorateur.

Vérifier

uv run pytest -q doit se terminer sans failed ni error. Les tests désélectionnés (deselected) sont les tests integration.

Ce que contrôle make lint

make lint ne modifie rien et échoue au premier problème (Makefile:11-16) :

  1. ruff format --check . : mise en forme.
  2. ruff check . : règles de style, dont les annotations de type obligatoires.
  3. pyrefly check src tests examples docs/tools : vérification des types, sur des chemins explicites.
  4. bandit -c pyproject.toml -r src examples : sécurité du code.
  5. python skills/piighost-docs/scripts/audit.py : audit des pages de documentation.

Comment la suite est organisée

DossierContenu
tests/components/Un sous-dossier par étape, c'est-à-dire détecteurs, liste à masquer et liste à laisser en clair, chevauchements, expansion, liens, résolveurs, anonymiseur, jetons, garde-fous
tests/pipeline/Pipeline simple, pipeline de conversation, correction humaine, listes intégrées au pipeline
tests/conversation_memory/, tests/crypto/Stockages et chiffrement
tests/config/, tests/cli/, tests/test_catalog.pyConfiguration, ligne de commande, catalogue
tests/integrations/LangChain, Pydantic AI, LlamaIndex, Claude Code, client HTTP
tests/observation/Spans OpenTelemetry et masquage des traces
tests/models/, tests/text/Modèles de données, limites de mots, espaces, découpage
tests/regression/API publique et imports sans dépendances optionnelles
tests/skills/test_docs_audit.pyLe script d'audit de la documentation

Écrire un test

  1. Placez le fichier dans le dossier de l'étape testée, sur le modèle du test voisin.
  2. Utilisez ExactMatchDetector({"Claire Dubois": "PERSON"}) comme détecteur, pour ne charger aucun modèle.
  3. Pour un stockage, utilisez InMemoryConversationMemory(), ou fakeredis pour Redis comme tests/conversation_memory/test_redis.py:21-27.
  4. Si le test exige une dépendance optionnelle, appelez pytest.importorskip("nom_du_module").
  5. Si le test charge un vrai modèle (torch, gliner2, spacy, transformers), marquez-le @pytest.mark.integration.
  6. Pour un nouveau détecteur, ajoutez aussi son constructeur à DETECTORS dans tests/components/detector/test_contract.py.

Vérifier

uv run pytest chemin/du/test.py -v
make lint

Ce que la CI GitHub exécute

WorkflowDéclencheurCe qu'il lance
ci.yml, tâche lintpush et pull request sur master et develop, sauf changements de doc seulsuv sync --locked --dev, puis make lint (Python 3.13)
ci.yml, tâche auditidempip-audit sur toutes les dépendances verrouillées, avec une vulnérabilité nltk acquittée
ci.yml, tâche testsaprès lint et audituv run pytest --cov=piighost sur Python 3.11, 3.12, 3.13 et 3.14
integration.ymlchaque nuit à 03:00 UTC, ou à la mainuv sync --all-extras --all-groups, modèle spaCy en_core_web_sm, puis pytest -m integration

Un changement qui ne touche que des fichiers .md, docs/ ou LICENSE ne déclenche pas ci.yml (paths-ignore).

Ce qui ne tourne nulle part en CI

Le groupe dev installe les extras config, argon2, crypto, redis, mistral, langchain, pydantic-ai, observation, fuzzy, sqlalchemy (pyproject.toml:150-151). Il n'installe ni llama-index, ni gliner2, ni spacy, ni transformers, ni presidio.

  • Dans la tâche tests, les tests qui demandent ces bibliothèques par importorskip sont sautés.
  • Dans integration.yml, ces bibliothèques sont installées, mais -m integration ne sélectionne que les tests marqués integration.

Les tests sautés et non marqués ne tournent donc dans aucune tâche. Ce sont notamment :

  • tests/integrations/llama_index/ (les deux fichiers)
  • les entrées gliner2, transformers, presidio et spacy de tests/components/detector/test_contract.py
  • tests/components/guard/test_gliner2_guard.py
  • tests/components/detector/ner/test_presidio.py, et les tests non marqués de test_spacy.py et test_transformers.py
  • tests/config/test_presidio_detector.py

Pour les lancer en local :

uv sync --all-extras --all-groups
uv run pytest -rs
uv sync

Revenez ensuite à l'environnement par défaut avec uv sync, puis relancez make lint. Un environnement chargé de tous les extras peut masquer une erreur d'import ou de type que la CI verrait.

Pièges

  • Un test sauté passe pour réussi. Lancez pytest -rs pour voir la liste et la raison de chaque saut.
  • Le conftest d'observation installe un traceur global pour toute la session. L'avertissement des traces en clair est donc filtré dans pyproject.toml:172-174, et seuls ses propres tests le vérifient.
  • pyrefly reçoit des chemins explicites. Sans eux, il ne vérifie rien dans un worktree git et échoue quand même (Makefile:8-10).
  • Les tests Redis utilisent fakeredis. Le comportement d'un vrai serveur ou d'un cluster n'est pas couvert.

Voir aussi Ajouter ou remplacer un composant pour les tests de contrat et d'imports.