Explain fuzz testing and set up a basic fuzz test
This tests coverage-guided fuzzing and toolchain wiring. Strong answer: defines fuzzing as automated input mutation driven by code coverage, contrasts it with hand-written examples, and sketches Go's FuzzXxx or Rust's cargo-fuzz setup.
WHAT THIS TESTS: This question probes whether you understand the fundamental difference between generative testing and example-based testing, and whether you have actually wired up a fuzz target in a modern language toolchain. At the senior level, interviewers care less about memorized API signatures and more about your mental model of coverage guidance, corpus evolution, and deterministic reproducibility. They want to see that you treat fuzzing as a systematic exploration of state space rather than a lucky random hammer.
A GOOD ANSWER COVERS: First, a crisp definition: fuzzing is automated testing that mutates inputs to find crashes, guided by code coverage feedback so that interesting inputs are evolved rather than discarded. Second, the contrast with example-based tests: table-driven tests verify known good and bad inputs, while fuzzing discovers unknown failure modes, especially security vulnerabilities and parser edge cases that humans did not anticipate. Third, a concrete toolchain sketch. In Go, you write a function named FuzzXxx that takes only a pointer to testing.F, call f.Add with seed corpus entries, then call f.Fuzz with a closure that takes a pointer to testing.T and the fuzzing arguments like string or byte slice. You run it with go test -fuzz=FuzzXxx. In Rust, you typically use cargo-fuzz, which leverages libfuzzer-sys; you define a fuzz_target macro, pass it bytes, and run cargo fuzz run target_name. Fourth, practical hygiene: fuzz targets must be fast, deterministic, and free of global state so parallel workers do not interfere, and failures must be reproducible from the minimized input.
COMMON WRONG ANSWERS: Calling fuzzing purely random or brute-force misses the entire point of coverage guidance and will immediately signal inexperience. Another red flag is suggesting that fuzzing replaces unit tests; it complements them but does not verify specific business logic or known regression cases. Confusing the seed corpus with the generated corpus is also common; the seed corpus provides starting examples, while the fuzzing engine builds a generated corpus based on coverage. Finally, forgetting to mention that fuzzing should run on platforms supporting coverage instrumentation, such as AMD64 or ARM64 in Go, suggests you have not operated fuzzers in production.
LIKELY FOLLOW-UPS: An interviewer might ask how you handle false positives or non-determinism in a fuzz target, how you integrate fuzzing into CI without infinite runtime, or how you minimize a crashing input. They may also ask about differential fuzzing, where you compare two implementations against each other, or how you sanitize memory issues alongside fuzzing in Rust with AddressSanitizer.
ONE CONCRETE EXAMPLE: Suppose you have a function ParseConfig that takes a string. In Go, your fuzz test function FuzzParseConfig receives a pointer to testing.F, adds a seed string like key equals value newline, then calls Fuzz with a closure that receives a pointer to testing.T and a string s. Inside, you call ParseConfig on s and skip errors so the fuzzer only cares about panics. The fuzzer starts from your seed, mutates the string, and uses coverage to learn which mutations reach new branches. If ParseConfig panics on an unexpected byte sequence, the fuzzer captures the input, minimizes it, and reports the failure.
Read the original → go.dev
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.