User Tools

Site Tools


golang:testing

Тестирование

источник: On testing Go code using the standard library

Обычно в тестировании используются t.Errorf и t.Fatalf функции, использующие идиомы fmt пакета.

Для примера:

package abs
 
import "testing"
 
func TestAbs(t *testing.T) {
	got := Abs(-1)
	if got != 1 {
		t.Errorf("Abs(-1) = %d; want 1", got)
	}
}
$ go test # on success
PASS
 
# On failure
$ go test
--- FAIL: TestAbs (0.00s)
    code_test.go:14: Abs(-1) = 3; want 1
FAIL
exit status 1
FAIL	github.com/henvic/exp	0.114s

Автор предпочитает использовать для сравнения assert пакет:

package abs
 
import (
	"testing"
 
	// testify is very used in the Go ecosystem.
	"github.com/stretchr/testify/assert"
)
 
func TestAbs(t *testing.T) {
	assert.Equal(t, 1, Abs(-1))
}
$ go test
--- FAIL: TestAbs (0.00s)
    code_test.go:14:
        	Error Trace:	/exp/code_test.go:14
        	Error:      	Not equal:
        	            	expected: 1
        	            	actual  : 3
        	Test:       	TestAbs
FAIL
exit status 1
FAIL	github.com/henvic/exp	0.152s

Вместо t.FailNow() лучше использовать testify/require:

t.Error("this doesn't stops the execution")
t.Fatal("this kills a test")
t.Error("not printed")
 
// $ go test ./...
// --- FAIL: TestAbs (0.00s)
//     code_test.go:13: this doesn't stop the execution
//     code_test.go:14: this kills a test
// FAIL
// FAIL	github.com/henvic/exp	0.115s
// FAIL
assert.Equal(t, 1, 2, "this doesn't stop the execution")
require.Equal(t, true, false, "this kills a test") // any errors after this won't be printed
assert.Equal(t, "a", "b", "not printed")

Сравнение структур

Пакет github.com/google/go-cmp используется для сравнения структур.

Обычно используется пакет reflect:

type Animal struct {
	Name  string
	Class string
	Sound string
}
 
var gecko = Animal{
	Name:  "Gecko",
	Class: "Reptile",
	Sound: "gecko",
}
 
var dog = Animal{
	Name:  "Dog",
	Class: "Mammal",
	Sound: "Bark",
}
 
if !reflect.DeepEqual(dog, gecko) {
	t.Error("dog and gecko are not the same animal")
}

Но результат сложно читать. Можно сделать лучше:

if !cmp.Equal(dog, gecko) {
	t.Errorf("animal is not a dog: %v", cmp.Diff(dog, gecko))
}
 
// or even:
 
if diff := cmp.Diff(dog, gecko); diff != "" {
	t.Errorf("animal is not a dog: %v", diff)
}

Результат:

$ go test
--- FAIL: TestAnimals (0.00s)
    code_test.go:37: animal is not a dog:   animalia.Animal{
        - 	Name:  "Dog",
        + 	Name:  "Gecko",
        - 	Class: "Mammal",
        + 	Class: "Reptile",
        - 	Sound: []string{"Bark"},
        + 	Sound: []string{"Click"},
          }
FAIL
exit status 1
FAIL	github.com/henvic/exp	0.146s

Для того, чтобы сравнивать только определенные части структуры можно использовать cmpopts:

if !cmp.Equal(got, dog,
	cmpopts.EquateApproxTime(time.Second), // Check if recorded was just created.
        cmpopts.IgnoreFields(Animal{}, "Age", "Location")) {
	t.Errorf("animal is not a dog: %v", cmp.Diff(dog, got))
}
 
if got.Age < 3 {
        t.Errorf("animal age should be at least 3, got %d instead", got.Age)
}
golang/testing.txt · Last modified: 2024/07/13 13:50 by Denis Evsyukov