Tema
/
Struktūrinis programavimas GO
Pamoka 13 / 14 Testavimas (go test) ~45 min
📖 Teorija

Lentelės testai — pagaunam 7 pamokos klaidą

Vienas įėjimas viename teste — per plona. Tikras funkcijas reikia tikrinti su keliais atvejais — įprastu, kraštiniu, klastingu. Rašyti atskirą Test… kiekvienam — triukšmas. Go idioma — lentelės pavidalo testas (table-driven): {įėjimas, want} eilučių sąrašas ir vienas ciklas, tikrinantis visas.

Prisimink charCount iš 7 pamokos — jis grąžina, kiek simbolių eilutėje. Štai jo lentelės testas:

func TestCharCount(t *testing.T) {
    cases := []struct {
        in   string
        want int
    }{
        {"obuolys", 7},
        {"ąžuolas", 7}, // lietuviškai: 7 simboliai, bet 9 baitai
        {"Go", 2},
        {"", 0},
    }
    for _, c := range cases {
        got := charCount(c.in)
        if got != c.want {
            t.Errorf("charCount(%q) = %d, want %d", c.in, got, c.want)
        }
    }
}

cases := []struct{…}{…}anoniminės struktūros sąrašas: vienkartinis tipas, egzistuojantis vien eilutėms išvardyti. Kiekviena eilutė — vienas atvejis; ciklas paleidžia visus ir praneša kiekvieną neatitikimą atskirai. Naujas atvejis — viena eilutė, ne nauja funkcija.

Dabar ašis — šis testas yra spąstai, pastatyti tikrai klaidai. Prisimink 7 pamoką: naivus būdas skaičiuoti simbolius yra len(s), ir jis klaidingas lietuviškai, nes len skaičiuoja baitus, o „ą" — 2 baitai. Tarkim, charCount vis dar turi klaidą:

func charCount(s string) int {
    return len(s) // KLAIDA: skaičiuoja BAITUS, ne simbolius
}

Paleisk go test:

--- FAIL: TestCharCount (0.00s)
    text_test.go:18: charCount("ąžuolas") = 9, want 7
FAIL
FAIL    yourapp   1.7s

Štai ji. Mašina pagavo — = 9, want 7 — tiksliai tą klaidą, įvardintą, dar prieš kuriam nors vartotojui įvedant lietuvišką pavadinimą. Jokio spoksojimo į išvestį, jokio spėliojimo: krentanti eilutė rodo tiesiai į sugedusį atvejį.

Dabar pataisyk charCount taip, kaip mokė 7 pamoka:

import "unicode/utf8"

func charCount(s string) int {
    return utf8.RuneCountInString(s) // skaičiuoja SIMBOLIUS
}

Paleisk go test dar kartą:

ok      yourapp   0.5s

O su -v matai jį praeinantį pavadinimu:

=== RUN   TestCharCount
--- PASS: TestCharCount (0.00s)
PASS

Tai ir yra visa testavimo esmė. 7 pamokos klaida slėpdavosi, kol konkretus įėjimas ją paliesdavo jau naudojime. Dabar testas ją prisimena amžinai: jei kada nors kas nors „supaprastins" charCount atgal į len, testas taps raudonas per kitą paleidimą. Testas — tai klaida, kurią pagauti reikia tik kartą.

Toliau: parašyk pilną testų failą savo programai — charCount, truncateRunes ir validateTitle, visi viename _test.go.