BudiBadu Logo

Samplebadu

Code with Example
BudiBadu Logo
Samplebadu

Go by Example: Unit Testing

Go 1.23

Learn Unit Testing with Go's built-in `testing` package. This example covers writing basic test functions, implementing table-driven tests for better coverage and maintainability, and running tests with the `go test` command.

Code

// main_test.go
package main

import (
    "testing"
)

func IntMin(a, b int) int {
    if a < b {
        return a
    }
    return b
}

func TestIntMinBasic(t *testing.T) {
    ans := IntMin(2, -2)
    if ans != -2 {
        t.Errorf("IntMin(2, -2) = %d; want -2", ans)
    }
}

func TestIntMinTableDriven(t *testing.T) {
    var tests = []struct {
        a, b int
        want int
    }{
        {0, 1, 0},
        {1, 0, 0},
        {2, -2, -2},
        {0, -1, -1},
        {-1, 0, -1},
    }

    for _, tt := range tests {
        ans := IntMin(tt.a, tt.b)
        if ans != tt.want {
            t.Errorf("got %d, want %d", ans, tt.want)
        }
    }
}

Explanation

Go's built-in testing package provides a lightweight but powerful testing framework. Tests live in _test.go files and are executed with go test.

Key testing concepts:

  • Table-Driven Tests: Define a slice of test cases (structs) and iterate over them. This is the idiomatic way to write tests in Go, making it easy to add new scenarios.
  • Subtests: Use t.Run("name", func(t *testing.T) {...}) inside your loop. This allows you to run specific test cases individually via the command line (e.g., go test -run TestIntMin/negative).
  • Helpers: Use t.Helper() in utility functions to ensure failure logs point to the test caller, not the helper function itself.

Code Breakdown

15
TestIntMinBasic is a simple unit test. It calls the function IntMin with inputs 2 and -2, and checks if the result matches the expected value (-2).
17
t.Errorf reports a test failure but allows the test function to continue executing. Use t.Fatal if you want to stop the test immediately after a failure.
21
TestIntMinTableDriven demonstrates table-driven tests. We define an anonymous struct slice 'tests' where each element represents a test case with inputs (a, b) and expected output (want).
32-37
We iterate over the test cases using a range loop. For each case, we call the function and verify the result. This approach is very scalable and readable.