Tarkibga o'tish

Go’da test yozish

Test kodning kutilgan natijani qaytarishini avtomatik tekshiradi. Go’da test yozish uchun standart testing paketi va go test buyrug‘i yetarli.

Birinchi test

Quyidagi paket ikki sonni qo‘shadi:

hisob.go
package hisob

func Add(a, b int) int {
    return a + b
}

Test fayli _test.go bilan tugaydi. Test funksiyasi TestXxx(t *testing.T) ko‘rinishida bo‘ladi:

hisob_test.go
package hisob

import "testing"

func TestAdd(t *testing.T) {
    got := Add(2, 3)
    want := 5
    if got != want {
        t.Errorf("Add(2, 3) = %d; %d kutilgan", got, want)
    }
}

Joriy paket testini go test, moduldagi barcha paketlarni esa go test ./... bajaradi:

go test
go test ./...

t.Errorf() xatoni qayd etib, testni davom ettiradi. Keyingi qadamni bajarish ma’nosiz yoki xavfli bo‘lsa, t.Fatalf() xatoni qayd etib, joriy test funksiyasini to‘xtatadi.

Table-driven test va subtest

Bir xil qoidani bir nechta qiymatda tekshirish uchun holatlarni jadvalda saqlash qulay:

func TestAdd(t *testing.T) {
    tests := []struct {
        name       string
        a, b, want int
    }{
        {name: "musbat", a: 2, b: 3, want: 5},
        {name: "manfiy", a: -2, b: -3, want: -5},
        {name: "nol", a: 4, b: 0, want: 4},
    }

    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            got := Add(tt.a, tt.b)
            if got != tt.want {
                t.Errorf("Add(%d, %d) = %d; %d kutilgan", tt.a, tt.b, got, tt.want)
            }
        })
    }
}

t.Run() har bir holatga alohida nom beradi. Bitta holat yiqilganda qolganlari bajarilishda davom etadi. Aniq subtestni go test -run 'TestAdd/musbat' bilan ishga tushirish mumkin.

Testlarni mustaqil saqlash

Test natijasi boshqa testning tartibi yoki oldingi holatiga bog‘liq bo‘lmasligi kerak. Global holatni o‘zgartirishdan, real foydalanuvchi fayllaridan va tashqi tarmoqqa keraksiz murojaatdan qoching.

Vaqtinchalik fayl kerak bo‘lsa, t.TempDir() testga tegishli katalog yaratadi va test tugagach uni tozalaydi:

func TestSave(t *testing.T) {
    dir := t.TempDir()
    path := filepath.Join(dir, "result.txt")
    if err := os.WriteFile(path, []byte("salom"), 0o600); err != nil {
        t.Fatalf("fayl yozilmadi: %v", err)
    }

    data, err := os.ReadFile(path)
    if err != nil {
        t.Fatalf("fayl o‘qilmadi: %v", err)
    }
    if string(data) != "salom" {
        t.Errorf("natija = %q; %q kutilgan", data, "salom")
    }
}

Bu snippet uchun importlar os, path/filepath va testing bo‘ladi.

Coverage

Coverage test vaqtida qaysi statementlar bajarilganini ko‘rsatadi:

go test -cover ./...
go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.out

Yuqori foiz kod to‘g‘riligini isbotlamaydi. Testlar muhim xatti-harakat, chegara qiymatlari va xato yo‘llarini mazmunli tekshirishi kerak.

Xulosa

Testlar _test.go fayllarida TestXxx funksiyalari sifatida yoziladi. go test ./... butun modulni tekshiradi. Jadval testlari ko‘p holatni izchil saqlaydi, t.Run() ularni nomlaydi, t.TempDir() esa faylli testlarni boshqa muhitdan ajratadi.