Organizing Table Tests in Go

Kanan Rahimov
5 min readJan 8, 2022
Organizing Table Tests in Go: two approaches to organizing use-cases for a unit test.

Table tests are one of the approaches to how to organize multiple use-cases for a single test. In this tutorial, I want to share my approach on how I organize table tests and structs used for it.

Standard Approach

Most IDEs can generate table-driven tests automatically. For this only thing, you need is to navigate to the function and use a command to generate the tests. In VS Code, you can do this by using the “ Go: Generate Unit Tests For Function” command.

Command to generate unit tests in VS Code.

For the following function:

func (mui *MemUI) Register(objs ...interface{}) error {
for _, obj := range objs {
err := mui.registerValue(obj)
if err != nil {
return err
}
}


return nil
}

View the source code at this state.

We will have something like this:

func TestMemUI_Register(t *testing.T) {
type fields struct {
memObjects map[string][]interface{}
}
type args struct {
objs []interface{}
}
tests := []struct {
name string
fields fields
args args
wantErr bool
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mui := &MemUI{
memObjects: tt.fields.memObjects,
}
if err := mui.Register(tt.args.objs...); (err != nil) != tt.wantErr {
t.Errorf("MemUI.Register() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}

VS Code also generates helper structs to better organize table-driven tests. A particularly interesting struct in our example is this one:

Struct for table tests.

It’s a slice of anonymous structs that will contain our testing use-cases. Example:

tests := []struct {
name string
fields fields
args args
wantErr bool
}{
{
name: "add pointer object",
fields: fields{memObjects: make(map[string][]interface{})},
args: args{objs: []interface{}{&Dummy1{Name: "dummy1"}}},
wantErr: false,
},
}

--

--