← Back to Go Course | Chapter 14: Standard Library & HTTP | Lesson 8 of 10

Writing Tests with the testing Package

Go's testing package lets you write little checkup scripts that automatically verify your code still works correctly every time you change something.

Writing a Basic Test

A test function is named TestXxx, takes a *testing.T, and calls t.Errorf (or t.Fatalf) when an expected result doesn't match the actual one. Here the same check is demonstrated directly in main so it can run and print output.

Note: Since Judge0 runs a single main.go, this example simulates test logic inside main() to show the assertion pattern -- real tests live in a _test.go file run via 'go test'.

Example: Writing a Basic Test

markup
package main

import "fmt"

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

func main() {
	got := add(2, 3)
	want := 5
	if got != want {
		fmt.Printf("FAIL: add(2,3) = %d, want %d\n", got, want)
	} else {
		fmt.Println("PASS: add(2,3) =", got)
	}
}

Table-Driven Tests

A table-driven test defines a slice of input/expected-output cases and loops over them, running the same assertion logic for each -- the idiomatic Go way to cover many cases without duplicating test code.

Example: Table-Driven Tests

markup
package main

import "fmt"

func square(n int) int {
	return n * n
}

func main() {
	cases := []struct {
		input, want int
	}{
		{2, 4},
		{3, 9},
		{5, 25},
	}
	for _, c := range cases {
		got := square(c.input)
		status := "PASS"
		if got != c.want {
			status = "FAIL"
		}
		fmt.Printf("%s: square(%d) = %d\n", status, c.input, got)
	}
}

Errorf vs Fatalf

t.Errorf marks the test as failed but lets it keep running (useful for reporting multiple issues in one test), while t.Fatalf marks it failed and immediately stops that test function, useful when continuing would panic.

Example: Errorf vs Fatalf

markup
package main

import "fmt"

func divide(a, b int) (int, bool) {
	if b == 0 {
		return 0, false
	}
	return a / b, true
}

func main() {
	if _, ok := divide(10, 0); !ok {
		fmt.Println("caught invalid division, stopping this check (like t.Fatalf)")
	}
	fmt.Println("continuing with other checks (like t.Errorf would allow)")
}
Common Mistakes
  1. Naming a test function without the exact Test prefix (and capitalized), which 'go test' won't discover and run.
  2. Forgetting a test function must take exactly one parameter, *testing.T, or it won't be recognized as a valid test.
  3. Using t.Fatal inside a goroutine spawned by a test, which is unsafe -- t methods must be called from the test's own goroutine.
Chapter Summary
  • Test functions live in _test.go files and are named TestXxx, taking a *testing.T parameter.
  • t.Errorf reports a failure but lets the test continue; t.Fatalf reports a failure and stops immediately.
  • 'go test' automatically discovers and runs every TestXxx function in a package.
  • Table-driven tests, iterating over a slice of input/expected pairs, are the idiomatic Go testing style.

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.