CodeBlanks Logo Icon CodeBlanks

Summary - Testing

Combine table tests and helpers to write a math test.

Testing summary

The Go testing toolbox: _test.go files, TestXxx(t *testing.T), t.Errorf/t.Fatalf, table tests + t.Run, t.Helper/t.Cleanup/t.TempDir, ExampleXxx + // Output:. On the command line: -run, -v, -race, -cover.

Taking dependencies as interfaces (e.g. io.Writer, a repository interface) makes code easy to test with fakes.

A fuzz test example

A fuzz test checks a property that "must hold for every input":

func FuzzTersCevir(f *testing.F) {
    f.Add("merhaba")
    f.Fuzz(func(t *testing.T, s string) {
        if Ters(Ters(s)) != s {
            t.Errorf("çift ters %q != %q", Ters(Ters(s)), s)
        }
    })
}

Failing inputs it finds are saved under testdata/fuzz/ and also run in later ordinary tests.

Practice Property test

Write Ters(s string) string using runes. Print whether the property Ters(Ters(s)) == s holds for all of the inputs "gopher", "çğü" and "".

Starter code

main.go
package main

import "fmt"

func main() {
    // buraya yaz
}

Sample solution

main.go
package main

import "fmt"

func Ters(s string) string {
    r := []rune(s)
    for i, j := 0, len(r)-1; i < j; i, j = i+1, j-1 {
        r[i], r[j] = r[j], r[i]
    }
    return string(r)
}

func main() {
    hepsi := true
    for _, s := range []string{"gopher", "çğü", ""} {
        if Ters(Ters(s)) != s {
            hepsi = false
        }
    }
    fmt.Println(hepsi)
}

Expected output

true

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 What do <code>FuzzXxx</code> tests, added in Go 1.18, do?

  • Search for bugs with randomly generated inputs Correct answer
  • Run tests in parallel
  • Measure coverage
  • Run benchmarks

Explanation: go test -fuzz=FuzzParse derives new inputs from the given seeds and tries to find a panic or failing check.

2 Add a seed

Question
func FuzzParse(f *testing.F) {
    f.____("42")
    f.Fuzz(func(t *testing.T, s string) { Parse(s) })
}
Answer
func FuzzParse(f *testing.F) {
    f.Add("42")
    f.Fuzz(func(t *testing.T, s string) { Parse(s) })
}

Explanation: f.Add gives the fuzz engine a starting input (seed).

3 Test kind

Term Meaning
TestXxx Unit test
ExampleXxx Docs + test
BenchmarkXxx Performance measurement
FuzzXxx Random input

All lessons in Intermediate