Модульні уроки (1/5)
Пакет «тестування».
У Go тести є частиною stdlib: немає зовнішньої бібліотеки, немає фреймворку для налаштування. Усе, що вам потрібно, це файл *_test.go поруч із кодом, кілька функцій TestXxx та команда go test.
Основні умовні позначення
- Тестові файли називаються
<something>_test.goі знаходяться в тому самому пакеті, що й код, який вони перевіряють (або в пакеті<name>_testдля «тестів чорної скриньки»). - Тестові функції мають точний підпис:
func TestXxx(t *testing.T), деXxxпочинається з великої літери. - Ви імпортуєте
testingіз stdlib. - Ні
assertEquals: ви використовуєтеif got != want { t.Errorf(...) }з дієсловамиfmt.
// 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)
}
}Запустіть його за допомогою:
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 проти t.Fatal
Ось два основних дієслова, які сигналізують про невдачу:
| Метод | Ефект |
|---|---|
t.Log(args...) | Реєструється, але не виходить з ладу (видно лише з -v або в разі збою). |
t.Error(args...) | Журнали, позначає FAIL, продовжує тестову функцію. |
t.Errorf(fmt, ...) | Як Error з форматуванням. |
t.Fatal(args...) | Журнали, позначає FAIL, зупиняє тест (викликає runtime.Goexit). |
t.Fatalf(fmt, ...) | Як Fatal з форматуванням. |
Емпіричне правило: використовуйте Fatal, коли продовження не має сенсу (наприклад, невдале налаштування, неминуче розіменування нульового вказівника); інакше Error, що дозволяє побачити всі помилки за один прогін.
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
}Налаштування та демонтаж за допомогою t.Cleanup
Щоб звільнити ресурси в кінці тесту (або підтесту), використовуйте t.Cleanup замість defer:
func TestDB(t *testing.T) {
db := newTestDB(t)
t.Cleanup(func() { db.Close() })
// ... test
}Перевага перед defer: помічник, який створює db, може зареєструвати очищення всередині, тому абонентам не потрібно його запам’ятовувати.
Тестові помічники
Метод t.Helper() позначає функцію як «допоміжну»: коли тест не вдається, трасування стека пропускає допоміжну функцію та вказує безпосередньо на виклик:
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
}вправи
Визначте функцію TestSum, яка перевіряє Sum(2,3) == 5 за допомогою t.Errorf із відформатованим повідомленням.
Рішення доступне після 3 спроб
У TestDiv використовуйте t.Fatal, щоб негайно зупинити тест, якщо Div повертає неочікуване значення.
Рішення доступне після 3 спроб
У чому принципова різниця між t.Error і t.Fatal?
if err != nil {
t.???(err)
}