Two Ways to Fail
A test can report a problem in two ways, and the difference is what happens next:
t.Errorf marks the test as failed and keeps going. The rest of the test still runs, so one run can report several problems at once.
t.Fatalf marks the test as failed and stops it immediately. Use it when continuing makes no sense — the next lines would crash or produce noise.
Both have a plain twin without formatting: t.Error(...) and t.Fatal(...) just print their arguments.
t.Errorf: Report and Continue
When a test checks several cases in a row, t.Errorf is the right tool: a broken case is reported, and the following cases are still checked.
That way one go test run shows you the whole damage — not just the first broken case.
See every broken case at once
This Add ignores b, so all three checks fail. Because they use t.Errorf, all three messages appear in a single run — with t.Fatalf you would only see the first.
Output: Go test file and captured go test output
package calc
import "testing"
// Add has a bug: it ignores b.
func Add(a, b int) int {
return a
}
func TestAdd(t *testing.T) {
if got := Add(2, 2); got != 4 {
t.Errorf("Add(2, 2) = %d; want 4", got)
}
if got := Add(2, 3); got != 5 {
t.Errorf("Add(2, 3) = %d; want 5", got)
}
if got := Add(10, 1); got != 11 {
t.Errorf("Add(10, 1) = %d; want 11", got)
}
}
t.Fatalf: Stop at Once
Sometimes a failed check means the rest of the test cannot work. A typical case: the test first prepares a value, then inspects it. If the preparation already went wrong, inspecting would be useless or would even crash.
t.Fatalf stops the test right there. The checks after it never run — and that is the point.
Stop before the useless checks
Split has a bug (it splits on the wrong character), so 1 part comes back instead of 3. t.Fatalf reports it and stops — the check of the first part below is never reached.
Output: Go test file and captured go test output
package words
import (
"strings"
"testing"
)
// Split has a bug: it splits on ";" instead of ",".
func Split(s string) []string {
return strings.Split(s, ";")
}
func TestSplit(t *testing.T) {
parts := Split("one,two,three")
if len(parts) != 3 {
t.Fatalf("got %d parts, want 3 — cannot check them", len(parts))
}
// Never reached while the bug is there.
if parts[0] != "one" {
t.Errorf("first part = %q; want %q", parts[0], "one")
}
}
Error and Fatal Without Formatting
When you do not need %d or %q placeholders, use the plain forms: t.Error("message") and t.Fatal("message"). They behave exactly like their f twins — report and continue, or report and stop.
Plain messages
Two simple boolean checks with plain t.Error messages. Both pass here, so the messages stay silent and the run prints PASS.
Output: Go test file and captured go test output
package calc
import "testing"
func IsEven(n int) bool {
return n%2 == 0
}
func TestIsEven(t *testing.T) {
if !IsEven(4) {
t.Error("4 should be even")
}
if IsEven(3) {
t.Error("3 should not be even")
}
}