Go > Testing and Benchmarking > Unit Testing > Table-driven tests
Table-Driven Testing in Go
This example demonstrates how to use table-driven tests in Go for unit testing. Table-driven tests are a powerful way to write concise and comprehensive tests by defining a set of inputs and expected outputs in a table.
Introduction to Table-Driven Tests
Table-driven tests are a testing technique where you define a slice (or array) of test cases. Each test case includes input values and the expected output. The test function iterates through the test cases, running the function under test with each input and comparing the result to the expected output. This approach is efficient, readable, and makes it easy to add new test cases.
Example Function: Integer Addition
Here's a simple function, `Add`, which we will test using table-driven tests. This function takes two integers and returns their sum.
package main
// Add adds two integers.
func Add(a, b int) int {
return a + b
}
The Table-Driven Test
This is the table-driven test for the `Add` function: 1. **Define the Test Table:** A slice of structs is defined. Each struct represents a single test case. The fields `a`, `b` represent the inputs to the `Add` function, and `expected` is the expected output. 2. **Iterate through the Test Cases:** A `for...range` loop iterates over the test table. 3. **Run Each Test Case:** `t.Run` creates a subtest for each test case, making it easier to identify which test case failed. This is highly recommended. The `test.name` provides descriptive context in the test output. 4. **Call the Function Under Test:** The `Add` function is called with the inputs from the current test case. 5. **Assert the Result:** The result is compared to the expected output. If they don't match, `t.Errorf` is called to report the error.
package main
import "testing"
func TestAdd(t *testing.T) {
table := []struct {
name string
a, b int
expected int
}{
{"positive numbers", 2, 3, 5},
{"negative numbers", -1, -2, -3},
{"mixed numbers", 5, -2, 3},
{"zero values", 0, 0, 0},
{"one zero", 5, 0, 5},
}
for _, test := range table {
t.Run(test.name, func(t *testing.T) {
result := Add(test.a, test.b)
if result != test.expected {
t.Errorf("For input %d + %d, expected %d, but got %d", test.a, test.b, test.expected, result)
}
})
}
}
Running the Tests
To run the tests, save the code as `main.go` and `main_test.go` in the same directory. Then, open a terminal in that directory and run the command `go test`.
Real-Life Use Case Section
Table-driven tests are particularly useful when you have a function with multiple input parameters or boundary conditions that need to be thoroughly tested. For example, validating user input, parsing complex data structures, or handling different error scenarios.
Best Practices
t.Run
) to make it easier to understand the test results.
Interview Tip
During technical interviews, be prepared to discuss the benefits of table-driven testing and explain how you would use it to test a given function. Being able to articulate the advantages and demonstrate your understanding of the technique can be impressive.
When to use them
Table-driven tests are best used when you want to test different inputs for a specific function, or when you have a complicated method. They are not effective on every situation, but in these cases are quite powerful.
Alternatives
There are other testing approaches, like basic unit testing for simple functions, or property-based testing to have even more coverage. Alternatives depend heavily on the requirements.
pros
cons
FAQ
-
What happens if a test case fails?
If a test case fails, the `t.Errorf` function will record an error message. The `go test` command will report which test cases failed, including the name of the test case and the error message. -
Can I use different data types in the test table?
Yes, you can use any data types in the test table that are appropriate for the function you are testing. Just make sure that the data types in the table match the expected input and output types of the function. -
How can I add more test cases later?
To add more test cases, simply add more entries to the `table` slice. Make sure to provide a descriptive name for each new test case.