ruk·si

🐹 Go
Unit Testing

Updated at 2022-04-21 09:55

My other snippets related to testing:

Go has build-in unit testing.

  • Test file names should end with _test.go e.g. main_test.go.
  • Test file should be next to the file it tests or in the package directory it tests.
  • Test function names should start with Test e.g. TestPasses.
  • Run all tests in a directory with go test ./dir or go test ..
  • Run all tests with go test ./... at the project root.
package main

import (
    "fmt"
    "testing"
)

func TestThatPasses(t *testing.T) {
    // passes as nothing fails the test
}

func TestThatFails(t *testing.T) {
    t.Fail()
}

func TestThatFailsWithMessage(t *testing.T) {
    t.Errorf("This failed: %s!", "nothing")
}

func TestWithTableDrivenParametrization(t *testing.T) {
    // the test case table could also be a separate variable
    for _, tc := range []struct {
        a, b      int
        aIsBigger bool
    }{
        {0, 1, false},
        {1, 0, true},
        {2, -2, true},
        {0, -1, true},
        {-1, 0, false},
    } {
        name := fmt.Sprintf("%d_>_%d", tc.a, tc.b) // spaces are not allowed
        t.Run(name, func(t *testing.T) {           // runs a separate subtest
            ans := tc.a > tc.b
            if ans != tc.aIsBigger {
                t.Errorf("got %t, wanted %t", ans, tc.aIsBigger)
            }
        })
    }
}

// you can also create benchmarks through `testing.B`
// note that the benchmark must start with `Benchmark`
// and should use the `b.N` as the loop count
// you run benchmarks with `go test -bench .`
func BenchmarkComparison(b *testing.B) {
    for i := 0; i < b.N; i++ {
        _ = i > 2 // here would be the call to your code
    }
}

You can test processes. Simply use exec.Command to run a process and inspect the outcome. Can be used to unit test your command line workings or do some more elaborate integration tests.

package main

import (
    "fmt"
    "os"
    "os/exec"
    "testing"
)

func Crasher() {
    fmt.Println("going down in flames")
    os.Exit(1)
}

func TestCrasher(t *testing.T) {
    if os.Getenv("BE_CRASHER") == "1" {
        Crasher()
        return
    }
    cmd := exec.Command(os.Args[0], "-test.run=TestCrasher")
    cmd.Env = append(os.Environ(), "BE_CRASHER=1")
    err := cmd.Run()
    if e, ok := err.(*exec.ExitError); ok && e.ExitCode() == 1 {
        return
    }
    t.Fatalf("process ran with err %q, want exit status 1", err)
}