Maison > développement back-end > Golang > Démasquer les pièges cachés des tests dans Go : éviter les faux positifs

Démasquer les pièges cachés des tests dans Go : éviter les faux positifs

Susan Sarandon
Libérer: 2024-12-26 11:08:14
original
316 Les gens l'ont consulté

Unmasking Hidden Test Pitfalls in Go: Avoiding False Positives

Le cauchemar des tests serait un faux positif. « Tout passe ! Incroyable!" jusqu'à ce qu'à un moment inconnu dans le futur, toutes les mines explosent ensemble et fassent exploser votre équipe en enfer.

Il existe de nombreuses raisons pour lesquelles les tests peuvent échouer silencieusement.

Aujourd'hui, je vais parler d'une raison très fondamentale : je ne sais pas quels sont les tests.

Pourquoi tu ne sais pas quels sont les tests ?

La plupart des gens rejoignent un projet Go à mi-chemin. La plupart des gens apprennent une langue en l'utilisant dans la vie réelle.

Par conséquent, lorsque quelqu'un avait mis en place le projet avec un framework de test tel que testify, vous penseriez probablement que des méthodes comme celles-ci sont des tests.

func (suite *ExampleTestSuite) TestExample() {
    suite.Equal(5, suite.VariableThatShouldStartAtFive)
}
Copier après la connexion
Copier après la connexion

Vous ajoutez ensuite une autre méthode comme TestAnotherCase et constatez que cela fonctionne. Vous pensez que vous savez parfaitement ce que sont les tests.

Le test a différentes significations dans différents cadres

Un « test » dont vous parlez n’est peut-être pas le même test qu’un package Go.

À partir du package de tests intégré, un test est n'importe quelle fonction du formulaire

func TestXxx(*testing.T)
Copier après la connexion
Copier après la connexion

Bien sûr, étant donné que le package de test intégré a des fonctionnalités limitées, la plupart des projets utilisent testify/suite ou un autre package tiers similaire comme cadre de test. Qu'est-ce qu'un test du point de vue du témoin/suite ?

ajoutez toutes les méthodes commençant par "Test" pour ajouter des tests

Vous voyez, nous avons deux définitions différentes d'un test.

Le problème commence lors de l'utilisation d'un outil de test tiers

Lorsque vous utilisez certains outils comme la moquerie, vous lirez ce qui suit

vous n'aurez plus à craindre d'oublier l'appel à la méthode AssertExpectations … La méthode AssertExpectations est enregistrée pour être appelée à la fin des tests

Super ! "Il me suffit donc de créer une simulation et le package me préviendra lorsque les comportements attendus se produiront".

C’est là que se trouve le piège.

Quand moquerie dit à la fin des tests, cela signifie en fait la définition de testing , pas la définition de testify/suite.

Ainsi, lorsque vous avez le code suivant, vous verrez que TestA et TestB réussissent même s'ils devraient tous deux échouer, car la configuration fictive dans TestA est utilisée dans TestB.

package mockandsubtest

import (
    "fmt"
    "testing"

    "github.com/stretchr/testify/suite"
)

// Prod code
type ExternalService interface {
    Work()
}

type Server struct {
    externalService ExternalService
}

func NewServer(externalService ExternalService) *Server {
    return &Server{
        externalService: externalService,
    }
}

// Test code
type ServerSuite struct {
    suite.Suite
    ExternalService *MockExternalService
    Server
}

func TestServerSuite(t *testing.T) {
    suite.Run(t, &ServerSuite{})
}

// Run before all test cases
func (s *ServerSuite) SetupSuite() {
    s.ExternalService = NewMockExternalService(s.T())
    s.Server = Server{externalService: s.ExternalService}
}

// In this test, Work is set up to be called once but not called
func (s *ServerSuite) TestA() {
    fmt.Println("TestA is running")
    s.ExternalService.EXPECT().Work().Times(1)
}

// In this test, Work is called once unexpectedly
func (s *ServerSuite) TestB() {
    fmt.Println("TestB is running")
    s.Server.externalService.Work()
}

Copier après la connexion

Le résultat de l'exécution du code ci-dessus est

TestA is running
TestB is running
PASS
Copier après la connexion

Explication

Il s'avère que seul TestServerSuite est considéré comme un test du point de vue des tests et de la moquerie. C'est pourquoi AssertExpectations est appelée à la fin de TestServerSuite , même si TestA et TestB sont exécutés en interne par testify/suite.

Du point de vue de la moquerie, s.ExternalService devrait être appelé une fois et effectivement appelé une fois dans le cycle de vie de TestServerSuite. L'attente est donc comblée.

Comment atténuer ?

Il existe deux façons de combler le fossé entre témoigner/suite et tester.

La première méthode consiste à créer une nouvelle simulation avant chaque méthode de test, comme suit.

func (suite *ExampleTestSuite) TestExample() {
    suite.Equal(5, suite.VariableThatShouldStartAtFive)
}
Copier après la connexion
Copier après la connexion

Parfois, ce n'est pas pratique dans votre projet pour de nombreuses raisons, par exemple, la configuration d'une instance de serveur pour chaque scénario de test est trop coûteuse. Ensuite, vous pouvez essayer l'autre sens, qui s'affirme manuellement après chaque test.

La seconde consiste à ajouter un appel de AssertExpectations à la fin de chaque méthode de test. Par exemple, appelez AssertExpectations dans TearDownTest , qui est exécuté après chaque méthode de test.

func TestXxx(*testing.T)
Copier après la connexion
Copier après la connexion

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:dev.to
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal