ProgramGuru

Fuzz Testing

Start with Fuzz Testing

In this lesson, explore fuzz testing through one small Go program, and connect its output to the language rules behind it.

What you’ll learn

  • Explain the main purpose of fuzz testing.
  • Read and run the complete Go example in this lesson.
  • Apply the concept and recognize common mistakes.

Understand the idea

Fuzzing automatically mutates inputs to search for crashes and invariant violations. A fuzz target has the form FuzzXxx(f *testing.F) in a _test.go file, seeds known inputs with f.Add, and registers a callback with f.Fuzz.

Write a property that should hold for every valid input, not just a few fixed strings. Fuzz targets need bounded resource use.

Visualize how it works

Follow this diagram before executing the example. Check where a value or decision changes what runs next.

Visual explanation for fuzzFuzzing explores inputs beyond hand-picked cases.Seed examplesStep 1Mutate inputsStep 2Check invariantStep 3Save failuresStep 4Fuzzing explores inputs beyond hand-picked cases.
Fuzzing explores inputs beyond hand-picked cases.

Tools, syntax and practical notes

normalize_test.go

package main
import "testing"
func FuzzNormalize(f *testing.F) {
    f.Add("Go"); f.Add("")
    f.Fuzz(func(t *testing.T, input string) {
        once := normalize(input)
        if twice := normalize(once); twice != once { t.Fatalf("not idempotent: %q", input) }
    })
}

Run go test -fuzz FuzzNormalize -fuzztime 5s. Reference: Getting started with fuzzing.

Run a complete Go example

This example is a complete program. Save it as main.go or paste it into the Go Playground.

Go code

package main

import (
	"fmt"
	"strings"
)

func normalize(s string) string { return strings.ToLower(s) }
func main() {
	s := "GoLANG"
	result := normalize(s)
	fmt.Println("Idempotent:", normalize(result) == result)
}

Output

Idempotent: true

Trace what the program does

Lowercasing twice produces the same result as lowercasing once for this seed. A fuzz test can check this property over many generated strings.

Avoid common mistakes

  • Not all inputs are valid for every API; document invariants clearly.
  • Fuzzing can find counterexamples, but a finite run cannot prove every input safe.

Try it yourself

Write FuzzNormalize using seed values "Go" and "", then assert normalize(normalize(s)) == normalize(s).

Tip: Edit the example above, predict the output, and run the modified code to test your reasoning.

Check your understanding

What does a fuzz target aim to find?
Choose one answer. You can try again.

Answer and explanation

Inputs that violate a property or cause failures

Correct. Lowercasing twice produces the same result as lowercasing once for this seed.

What you should remember

You have practiced Fuzz Testing in a small, self-contained program. The important habit is to predict what runs, inspect the actual output and distinguish the language rule from the particular example.

Before continuing, make sure you can explain the program to someone who has not seen it, including the line that changes its result.

Reaching the recap and completing the quizzes are separate milestones.

    Next lesson: Testing Concurrent Programs →