Lancer et écrire les tests
En bref
piighosta 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éveloppement | uv sync |
| Lancer toute la suite rapide | uv run pytest |
| Lancer un test précis | uv run pytest tests/pipeline/test_pipeline.py -k "nom_du_test" |
| Lancer les tests qui chargent des modèles | uv run pytest -m integration |
| Corriger la mise en forme | make format |
| Passer le contrôle bloquant | make 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) :
ruff format --check .: mise en forme.ruff check .: règles de style, dont les annotations de type obligatoires.pyrefly check src tests examples docs/tools: vérification des types, sur des chemins explicites.bandit -c pyproject.toml -r src examples: sécurité du code.python skills/piighost-docs/scripts/audit.py: audit des pages de documentation.
Comment la suite est organisée
| Dossier | Contenu |
|---|---|
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.py | Configuration, 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.py | Le script d'audit de la documentation |
Écrire un test
- Placez le fichier dans le dossier de l'étape testée, sur le modèle du test voisin.
- Utilisez
ExactMatchDetector({"Claire Dubois": "PERSON"})comme détecteur, pour ne charger aucun modèle. - Pour un stockage, utilisez
InMemoryConversationMemory(), oufakeredispour Redis commetests/conversation_memory/test_redis.py:21-27. - Si le test exige une dépendance optionnelle, appelez
pytest.importorskip("nom_du_module"). - Si le test charge un vrai modèle (torch, gliner2, spacy, transformers), marquez-le
@pytest.mark.integration. - Pour un nouveau détecteur, ajoutez aussi son constructeur à
DETECTORSdanstests/components/detector/test_contract.py.
Vérifier
uv run pytest chemin/du/test.py -v
make lintCe que la CI GitHub exécute
| Workflow | Déclencheur | Ce qu'il lance |
|---|---|---|
ci.yml, tâche lint | push et pull request sur master et develop, sauf changements de doc seuls | uv sync --locked --dev, puis make lint (Python 3.13) |
ci.yml, tâche audit | idem | pip-audit sur toutes les dépendances verrouillées, avec une vulnérabilité nltk acquittée |
ci.yml, tâche tests | après lint et audit | uv run pytest --cov=piighost sur Python 3.11, 3.12, 3.13 et 3.14 |
integration.yml | chaque nuit à 03:00 UTC, ou à la main | uv 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 parimportorskipsont sautés. - Dans
integration.yml, ces bibliothèques sont installées, mais-m integrationne sélectionne que les tests marquésintegration.
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,presidioetspacydetests/components/detector/test_contract.py tests/components/guard/test_gliner2_guard.pytests/components/detector/ner/test_presidio.py, et les tests non marqués detest_spacy.pyettest_transformers.pytests/config/test_presidio_detector.py
Pour les lancer en local :
uv sync --all-extras --all-groups
uv run pytest -rs
uv syncRevenez 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 -rspour 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. pyreflyreç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.