Aide

Besoin d’aide ?

Posez votre question sur le Discord de MiniLab, dans le salon de cette page :

#questions-demarrage

Ouvrir le salon ↗

Pas encore membre ? Rejoindre le Discord, puis revenez sur ce bouton.

Ma progression

Sauvegarder ma progression

Chargement…

Votre progression est enregistrée dans ce navigateur, pour cette adresse seulement. Gardez ce code : il la restaure dans un autre navigateur, sur un autre ordinateur, ou si les données du site ont été effacées.

MINILAB-0-1C
Mentions légales
Affichage

Personnaliser l’affichage

PROJET MINILAB · PRÉPARER L’ENVIRONNEMENT / 03

Les tests : du rouge au vert.

À la fin de l’installation, vos tests ont tous échoué. Ce n’est pas une panne : c’est le point de départ du projet. Les tests sont écrits avant votre code, et votre travail consiste à les faire passer au vert, un par un. Cette page vous apprend à les lancer, à suivre votre progression et à lire un échec.

01

À quoi sert un test

Un test est une petite fonction Python qui appelle votre code avec une entrée connue, puis vérifie le résultat avec assert. Si la condition est vraie, le test passe ; sinon, il échoue et explique pourquoi. Voici l’un des tests de l’étape 1 : il vérifie que merge remplace bien chaque paire (1, 2) par le nouveau token 9.

tests/minilab/test_tokenizer.py, un test de l’étape 1
def test_merge_replaces_pairs_from_left_to_right():
    assert merge([1, 2, 1, 2, 3], (1, 2), 9) == [9, 9, 3]
    assert merge([5, 5, 5], (5, 5), 7) == [7, 5]

pytest trouve tout seul les fichiers dont le nom commence par test_, puis lance chaque fonction dont le nom commence aussi par test_. Le projet en compte 30, répartis en un fichier par étape. Ils utilisent de tout petits modèles, pour tourner en une seconde environ.

02

Écrits avant votre code : rouge, puis vert

Dans ce projet, les tests sont fournis avant le code qu’ils vérifient. C’est une méthode répandue chez les développeurs, le développement piloté par les tests (*test-driven development*, ou TDD) : on écrit d’abord ce que le code doit faire, puis on écrit le code jusqu’à ce que les tests passent. On parle de cycle rouge, puis vert : un test qui échoue s’affiche en rouge, un test qui passe en vert.

Une règle d’or : ne modifiez jamais les tests pour les faire passer. Ils décrivent ce que votre code doit faire ; si l’un d’eux échoue, c’est le code qu’il faut corriger.

03

Au départ, tout est rouge

Lancez tous les tests du projet. Avant la première étape, aucun fichier n’existe dans packages/minilab/ : chaque fichier de test commence par importer le module de son étape, et cet import échoue. pytest ne peut même pas charger les tests : il signale une erreur de collecte (*collection error*), marquée ERROR, pour chacun des 6 fichiers, puis s’interrompt.

  • Lancer tous les tests
    uv run pytest tests/minilab
Sortie attendue au départ (fin)
E   ModuleNotFoundError: No module named 'packages.minilab.model'
=========================== short test summary info ============================
ERROR tests/minilab/test_chat.py
ERROR tests/minilab/test_generate.py
ERROR tests/minilab/test_model.py
ERROR tests/minilab/test_server.py
ERROR tests/minilab/test_tokenizer.py
ERROR tests/minilab/test_train.py
!!!!!!!!!!!!!!!!!!! Interrupted: 6 errors during collection !!!!!!!!!!!!!!!!!!!!
============================== 6 errors in 1.79s ===============================
04

Suivre sa progression

Pendant que vous construisez une étape, lancez seulement ses tests. L’option -v (*verbose*) affiche chaque test sur sa ligne, avec PASSED ou FAILED. Une étape est terminée quand tous ses tests passent.

  • Les tests de l’étape en cours, un par ligne (ici l’étape 1)
    uv run pytest tests/minilab/test_tokenizer.py -v
Sortie attendue, étape 1 terminée
tests/minilab/test_tokenizer.py::test_merge_replaces_pairs_from_left_to_right PASSED [ 16%]
tests/minilab/test_tokenizer.py::test_pre_tokenization_keeps_the_space_with_the_next_word PASSED [ 33%]
tests/minilab/test_tokenizer.py::test_training_learns_the_requested_number_of_merges PASSED [ 50%]
tests/minilab/test_tokenizer.py::test_encode_decode_round_trip_and_compression PASSED [ 66%]
tests/minilab/test_tokenizer.py::test_special_tokens_only_when_allowed PASSED [ 83%]
tests/minilab/test_tokenizer.py::test_stream_decoder_waits_for_the_missing_bytes PASSED [100%]

============================== 6 passed in 0.01s ===============================

Pour voir où en est tout le projet, il faut une option de plus. Sans elle, pytest s’arrête dès qu’un fichier de test ne peut pas être chargé : tant que les étapes suivantes n’existent pas, il ne lancerait même pas les tests de l’étape 1. Avec --continue-on-collection-errors, il lance tout ce qui peut l’être et fait le compte.

  • Tous les tests, même si des étapes manquent encore
    uv run pytest tests/minilab -q --continue-on-collection-errors
Sortie attendue après l’étape 1 (fin)
ERROR tests/minilab/test_chat.py
ERROR tests/minilab/test_generate.py
ERROR tests/minilab/test_model.py
ERROR tests/minilab/test_server.py
ERROR tests/minilab/test_train.py
6 passed, 5 errors in 0.45s

Cette dernière ligne est votre barre de progression : 6 passed, 5 errors après l’étape 1, et 30 passed quand le projet est complet. L’option -q (*quiet*) raccourcit l’affichage.

05

Lire un échec

Quand votre code se trompe, le test passe au rouge et pytest explique pourquoi. Voici ce qu’il affiche si, dans merge, on écrit par erreur i += 1 au lieu de i += 2 après une fusion :

Sortie d’un test qui échoue (extrait)
=================================== FAILURES ===================================
_________________ test_merge_replaces_pairs_from_left_to_right _________________

    def test_merge_replaces_pairs_from_left_to_right():
>       assert merge([1, 2, 1, 2, 3], (1, 2), 9) == [9, 9, 3]
E       assert [9, 2, 9, 2, 3] == [9, 9, 3]
E         
E         At index 1 diff: 2 != 9
E         Left contains 2 more items, first extra item: 2

tests/minilab/test_tokenizer.py:15: AssertionError
...
========================= 2 failed, 4 passed in 0.02s ==========================

Lisez-le de haut en bas. Le titre donne le nom du test. Le chevron > montre la ligne qui a échoué. Les lignes E comparent la valeur obtenue, à gauche, et la valeur attendue, à droite : ici, merge a laissé passer le 2 qui suivait chaque fusion. La dernière ligne donne le fichier et le numéro de ligne du test. Une seule erreur peut faire échouer plusieurs tests : corrigez la première, puis relancez.

06

Trois options utiles

Quelques options de pytest rendent le travail plus confortable. -x s’arrête au premier échec, pour corriger une erreur à la fois. -k ne lance que les tests dont le nom contient un mot. Et --lf (*last failed*) relance seulement les tests qui ont échoué la dernière fois.

Options de pytest
  • S’arrêter au premier échec
    uv run pytest tests/minilab/test_tokenizer.py -x
  • Lancer seulement les tests dont le nom contient « merge »
    uv run pytest tests/minilab/test_tokenizer.py -k merge
  • Relancer seulement les tests qui ont échoué
    uv run pytest tests/minilab --lf

VÉRIFIER SES CONNAISSANCES

Valider cette étape

Répondez aux trois questions pour débloquer la suite. Vous pouvez réessayer autant de fois que nécessaire.

Chargement de la progression…

Mise en ligne le