Leçons du module (1/5)
Le package testing
Dans Go, les tests font partie de la stdlib : pas de bibliothèque externe, pas de framework à configurer. Tout ce dont vous avez besoin est un fichier *_test.go à côté du code, quelques fonctions TestXxx et la commande go test.
##Conventions de base
- Les fichiers de test sont nommés
<something>_test.goet se trouvent dans le même package que le code qu'ils testent (ou dans un package<name>_testpour les "tests en boîte noire"). - Les fonctions de test ont une signature exacte :
func TestXxx(t *testing.T)oùXxxcommence par une lettre majuscule. - Vous importez
testingdepuis stdlib. - Pas de
assertEquals: vous utilisezif got != want { t.Errorf(...) }avec les verbesfmt.
// math.go
package math
func Sum(a, b int) int { return a + b }
// math_test.go
package math
import "testing"
func TestSum(t *testing.T) {
got := Sum(2, 3)
if got != 5 {
t.Errorf("Sum(2,3) = %d; voglio %d", got, 5)
}
}Exécutez-le avec :
go test ./... # all packages in the module
go test -v ./pkg # verbose: prints test names
go test -run TestSum # only tests matching the regext.Error contre t.Fatal
Ce sont les deux verbes de base pour signaler un échec :
| Méthode | Effet |
|---|---|
t.Log(args...) | Enregistre mais n'échoue pas (visible uniquement avec -v ou en cas d'échec). |
t.Error(args...) | Enregistre, marque FAIL, continue la fonction de test. |
t.Errorf(fmt, ...) | Comme Error avec formatage. |
t.Fatal(args...) | Enregistre, marque FAIL, arrête le test (appelle runtime.Goexit). |
t.Fatalf(fmt, ...) | Comme Fatal avec formatage. |
Règle générale : utilisez Fatal lorsque continuer n'a aucun sens (par exemple, échec de la configuration, déréférencement imminent du pointeur nul) ; sinon Error, qui vous permet de voir tous les échecs en une seule exécution.
func TestOpen(t *testing.T) {
f, err := os.Open("fixtures/sample.txt")
if err != nil {
t.Fatal(err) // if it doesn't open, the next steps would fail on nil
}
defer f.Close()
// ... assert on content with t.Errorf
}Installation et démontage avec t.Cleanup
Pour libérer des ressources à la fin d'un test (ou sous-test), utilisez t.Cleanup au lieu de defer :
func TestDB(t *testing.T) {
db := newTestDB(t)
t.Cleanup(func() { db.Close() })
// ... test
}L'avantage par rapport à defer : l'assistant qui crée db peut enregistrer le nettoyage en interne, les appelants n'ont donc pas besoin de s'en souvenir.
Aides aux tests
La méthode t.Helper() marque une fonction comme « assistant » : lorsqu'un test échoue, la trace de la pile ignore la fonction d'assistance et pointe directement vers l'appelant :
func mustParseInt(t *testing.T, s string) int {
t.Helper()
n, err := strconv.Atoi(s)
if err != nil {
t.Fatalf("parse %q: %v", s, err)
}
return n
}Exercices
Définissez la fonction TestSum qui vérifie Sum(2,3) == 5 en utilisant t.Errorf avec un message formaté.
Solution disponible après 3 tentatives
Dans TestDiv, utilisez t.Fatal pour arrêter immédiatement le test si Div renvoie une valeur inattendue.
Solution disponible après 3 tentatives
Quelle est la différence fondamentale entre t.Error et t.Fatal ?
if err != nil {
t.???(err)
}