Что такое unit тесты
Юнит-тесты (unit tests) — это тесты, предназначенные для проверки корректности работы отдельных модулей или единиц кода, таких как функции или методы. Основная цель юнит-тестов — убедиться, что каждый модуль кода работает как ожидается. Играют ключевую роль в поддержке качества и надежности кода.
Зачем они нужны?
1. Обнаружение ошибок на ранней стадии:
- Юнит-тесты помогают выявлять ошибки и проблемы в коде на самых ранних этапах разработки, что снижает затраты на их исправление.
2. Документация кода:
- Хорошо написанные юнит-тесты служат живой документацией для кода, показывая, как именно должны работать функции и методы.
3. Поддержка рефакторинга:
- Наличие юнит-тестов делает процесс рефакторинга безопаснее, так как тесты помогают убедиться, что изменения в коде не нарушили его корректную работу.
4. Повышение уверенности в коде:
- Юнит-тесты обеспечивают уверенность в том, что код работает правильно, что особенно важно при добавлении новых функций или исправлении ошибок.
Как их писать?
1. Создание тестовых файлов:
- Тестовые файлы в Go должны оканчиваться на `_test.go`.
- Тестовые функции должны начинаться с `Test` и принимать один аргумент типа `*testing.T`.
2. Пример написания юнит-теста:
Рассмотрим пример, где у нас есть функция, которая складывает два числа, и мы пишем для неё юнит-тест.
```go
// main.go
package main
func Add(a, b int) int {
return a + b
}
```
```go
// main_test.go
package main
import "testing"
func TestAdd(t *testing.T) {
result := Add(2, 3)
expected := 5
if result != expected {
t.Errorf("Add(2, 3) = %d; want %d", result, expected)
}
}
```
3. Запуск юнит-тестов:
- Чтобы запустить юнит-тесты, используйте команду `go test` в терминале.
```sh
$ go test
```
4. Тестирование с таблицей (table-driven tests):
- Table-driven tests позволяют легко добавлять новые тестовые случаи и улучшать читаемость тестов.
```go
package main
import "testing"
func TestAdd(t *testing.T) {
tests := []struct {
a, b, expected int
}{
{1, 2, 3},
{0, 0, 0},
{-1, -1, -2},
{2, 2, 4},
}
for _, tt := range tests {
result := Add(tt.a, tt.b)
if result != tt.expected {
t.Errorf("Add(%d, %d) = %d; want %d", tt.a, tt.b, result, tt.expected)
}
}
}
```
Лучшие практики
1. Соблюдайте атомарность:
- Каждый юнит-тест должен проверять только одну конкретную функцию или метод и проверять один аспект её поведения.
2. Используйте понятные названия:
- Имена тестовых функций должны быть понятными и отражать их цель. Например, `TestAdd` для тестирования функции `Add`.
3. Проверяйте крайние случаи:
- Убедитесь, что ваши тесты проверяют крайние случаи и потенциальные ошибки, такие как нулевые значения, отрицательные числа и переполнения.
4. Регулярно запускайте тесты:
- Регулярно запускайте тесты, особенно перед коммитами и релизами, чтобы убедиться в отсутствии регрессий.
5. Используйте mocking, если необходимо:
- При тестировании функций, которые зависят от внешних ресурсов (таких как базы данных или API), используйте мокирование (mocking) для изоляции тестов.
Юнит-тесты проверяют отдельные функции или методы на корректность их работы. Они помогают выявлять ошибки на ранней стадии, служат документацией и поддерживают безопасный рефакторинг кода. Пишутся в файлах с суффиксом `_test.go` и запускаются с помощью команды `go test`.
June 2, 2024, easyoffer