Table-testing/table-driven testing in Go has been a thing for a very long time, yet there are still articles coming out about it that add some new ideas at least for the way I use them. Exactly this happened a couple of days ago when I stumbled (thanks to a co-worker) upon Dominik Braun’s article titled “Writing Clean and Efficient Table-Driven Unit Tests in Go” over on SemaphoreCI.com.
First of all, he gives a great rundown of what table-testing/table-driven testing is and how to get started. He then also goes into a few guidelines on how to make them more efficient and readable over the long run. I use pretty much all of them already but two which I will from now on most likely try to incorporate into my process:
Maps instead of slices
Traditionally, I’ve been putting my test cases into a slice of structs. This kind of follows the semantics of a table by having “rows” in fixed order. One thing that’s always annoying there, though, is that I also have to pass some sort of “name” property to my test structs so that I can distinguish the test runs.
Dominik now mentions the use of maps instead of slices here.
tests := map[string]struct {
Input string
ExpectedOutput string
}{
"simple": {
Input: "hello",
ExpectedOutput: "world",
},
}
This not only makes adding the extra name-property redundant but also makes them run not necessarily in the order you’ve defined, adding some extra randomness to the execution.
Helper structs
The other little annoyance I always have with table-testing is that my test structs tend to get messy especially for more complex parameter-setups. For this he suggests to create helper structs to better group the input parameter and the expected output aspects of a run:
type Input struct {
Value string
}
type ExpectedOutput struct {
Output string
}
tests := map[string]struct {
Input Input
ExpectedOutput ExpectedOutput
}{
"simple": {
Input: Input{"hello"},
ExpectedOutput: ExpectedOutput{"world"},
},
}
This is especially nice if you also test functions that may or may not return errors or have lots of parameters (for which you could also use prototype functions).
Do you want to give me feedback about this article in private? Please send it to comments@zerokspot.com.
Alternatively, this website also supports Webmentions. If you write a post on a blog that supports this technique, I should get notified about your link π