Maison >développement back-end >Golang >Conseils de refactorisation pour les tests unitaires de la fonction Go
Pour améliorer la maintenabilité et la lisibilité des tests unitaires des fonctions Go, nous pouvons : Extraire des fonctions d'assertion pour simplifier le code. Utilisez des tests basés sur des tables pour organiser les données de test. Écrivez des interfaces moqueuses pour tester l'interaction entre les fonctions et les composants. Exécutez des tests précis pour isoler et déboguer les problèmes. Appliquer des outils de couverture pour garantir l’exhaustivité des tests et guider les améliorations.
Lorsque nous avons un projet Go vaste et complexe, la maintenance et la lisibilité des tests unitaires fonctionnels peuvent devenir un grand défi. Pour relever ce défi, nous pouvons mettre en œuvre certaines techniques de refactoring pour améliorer la maintenabilité et la lisibilité de nos tests.
Si le code de test contient de nombreuses assertions identiques, vous pouvez extraire la fonction d'assertion pour simplifier le code. Par exemple, nous pouvons définir une fonction AssertEqual
pour vérifier si deux valeurs sont égales : AssertEqual
函数来检查两个值是否相等:
import "testing" func AssertEqual(t *testing.T, expected, actual interface{}) { if expected != actual { t.Errorf("Expected %v, got %v", expected, actual) } }
表驱动的测试可以帮助组织和简化测试数据。它允许我们使用一个表来提供不同的输入和期望输出,然后对每个输入执行测试。例如,我们可以编写一个表驱动的测试来检查 Max
函数:
import ( "testing" "github.com/stretchr/testify/assert" ) func TestMax(t *testing.T) { tests := []struct { name string input []int expected int }{ {"Empty slice", []int{}, 0}, {"Single element", []int{1}, 1}, {"Multiple elements", []int{1, 2, 3}, 3}, } for _, tt := range tests { actual := Max(tt.input) assert.Equal(t, tt.expected, actual) } }
mocking 接口允许我们测试函数在与其他组件交互时的行为。我们可以使用一个 mocking 框架(如 mockery
)来生成 mock 对象,该对象实现了我们关心的接口,但我们可以控制其行为。例如,我们可以编写一个 mockDatabase
来测试一个使用数据库的函数:
package main import ( "database/sql" "fmt" "time" "github.com/stretchr/testify/mock" ) // MockDatabase is a mock database for testing purposes. type MockDatabase struct { mock.Mock } // Query implements the Query method of a mock database. func (m *MockDatabase) Query(query string, args ...interface{}) (*sql.Rows, error) { ret := m.Called(query, args) return ret.Get(0).(*sql.Rows), ret.Error(1) } // GetUserByUsernameAndPassword implements the GetUserByUsernameAndPassword method of a mock database. func (m *MockDatabase) GetUserByUsernameAndPassword(username, password string) (*User, error) { ret := m.Called(username, password) return ret.Get(0).(*User), ret.Error(1) } // User represents a user in the database. type User struct { Username string Password string LastLogin time.Time } // main is the entry point for the program. func main() { mockDB := &MockDatabase{} mockDB.On("GetUserByUsernameAndPassword", "john", "password").Return(&User{ Username: "john", Password: "password", LastLogin: time.Now(), }, nil) user, err := GetUser(mockDB, "john", "password") if err != nil { fmt.Println("Error getting user:", err) } else { fmt.Println("Welcome back, ", user.Username) } }
细粒度的测试专注于测试函数的小部分功能。通过运行细粒度的测试,我们可以更轻松地隔离和调试问题。例如,我们可以编写一个测试来检查 Max
import "testing" func TestMaxElement(t *testing.T) { tests := []struct { name string input []int expected int }{ {"Empty slice", []int{}, 0}, {"Single element", []int{1}, 1}, {"Multiple elements", []int{1, 2, 3}, 3}, } for _, tt := range tests { actual := MaxElement(tt.input) assert.Equal(t, tt.expected, actual) } }2. Utiliser les tests pilotés par table Les tests pilotés par table peuvent aider à organiser et à simplifier les données de test. Cela nous permet d'utiliser un tableau pour fournir différentes entrées et sorties souhaitées, puis d'effectuer des tests sur chaque entrée. Par exemple, nous pouvons écrire un test piloté par table pour vérifier la fonction
Max
: rrreee
3 Écrire une interface moqueuse L'interface moqueuse nous permet de tester le comportement d'une fonction lors de l'interaction avec. d'autres composants. Nous pouvons utiliser un framework moqueur (tel quemockery
) pour générer des objets simulés qui implémentent l'interface qui nous intéresse, mais dont nous pouvons contrôler le comportement. Par exemple, nous pouvons écrire une mockDatabase
pour tester une fonction qui utilise une base de données : rrreee
4 Exécutez des tests fins 🎜🎜Les tests fins se concentrent sur le test d'une petite partie des fonctionnalités de. la fonction. En exécutant des tests précis, nous pouvons plus facilement isoler et déboguer les problèmes. Par exemple, nous pouvons écrire un test pour vérifier si la fonctionMax
renvoie l'élément maximum : 🎜rrreee🎜 5. Utiliser les outils de couverture 🎜🎜Les outils de couverture peuvent nous aider à identifier quelles lignes de code sont couvertes par les tests . Cela nous aide à garantir que notre suite de tests est complète et peut nous guider dans la rédaction de tests supplémentaires pour couvrir le code manquant. 🎜🎜Conclusion🎜🎜En adoptant ces techniques de refactoring, nous pouvons améliorer la maintenabilité et la lisibilité des tests unitaires fonctionnels dans les projets Go. En extrayant des fonctions d'assertion, en utilisant des tests basés sur des tables, en écrivant des interfaces moqueuses, en exécutant des tests fins et en utilisant des outils de couverture, nous pouvons écrire un code de test plus fiable et plus maintenable. 🎜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!