How do you write a table-driven test in Go?
Tests idiomatic Go test design. A strong answer: slice/map of structs with inputs/expected outputs, loop with t.Run for named subtests, and cite DRY code, parallelization, and failure isolation. Red flag: separate Test functions per case or omitting t.Run.
WHAT THIS TESTS: This question probes whether you understand idiomatic Go test organization and can avoid duplication without sacrificing clarity. Interviewers want to see that you treat tests as first-class code that should be maintained, not just generated.
A GOOD ANSWER COVERS: First, define a table as a slice or map of structs where each entry holds inputs, expected outputs, and optionally a name. Using a map has the added benefit of randomizing execution order, which helps catch hidden dependencies between cases. Second, write a single test function that ranges over the table and calls t.Run with the case name and a closure that executes the actual assertion. Third, explain that t.Run creates subtests, which means each case appears independently in test output and can be run in isolation via the command line. Fourth, highlight the practical benefits: you write the assertion logic once, you can add t.Parallel inside the subtest closure, and failures tell you exactly which input broke without reading line numbers. Fifth, note that t.Errorf keeps executing subsequent cases while t.Fatalf stops the current subtest, so choosing between them matters.
COMMON WRONG ANSWERS: A major red flag is suggesting a separate top-level Test function for every scenario. That leads to massive copy-paste and makes updates painful. Another red flag is iterating over the table without t.Run, which collapses all failures into one anonymous blob and prevents running individual cases. A subtle mistake is capturing the loop variable incorrectly in the closure, though this is largely fixed in Go 1.22; mentioning it shows depth.
LIKELY FOLLOW-UPS: The interviewer might ask when to use a slice versus a map for the table, or how to parallelize table-driven tests safely. They might also ask how to share setup code between subtests, or how table-driven tests interact with benchmarks and fuzzing.
ONE CONCRETE EXAMPLE: Suppose you are testing a function that reverses a string. You define tests as a map with string keys and struct values holding input and want fields, including cases for empty strings, ASCII characters, and multi-byte glyphs. Inside TestReverse, you range over the map, call t.Run with the name and a closure that marks the subtest parallel, then compare Reverse of the input to the expected value and fail with a formatted message if they differ. This gives you named, parallel, independent subtests for every case.
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.