Test Tables

Use table-driven tests with subtests to avoid duplicating code when the coretest logic is repetitive.

BadGood
  1. // func TestSplitHostPort(t testing.T)
  2. host, port, err := net.SplitHostPort("192.0.2.0:8000")
  3. require.NoError(t, err)
  4. assert.Equal(t, "192.0.2.0", host)
  5. assert.Equal(t, "8000", port)
  6. host, port, err = net.SplitHostPort("192.0.2.0:http")
  7. require.NoError(t, err)
  8. assert.Equal(t, "192.0.2.0", host)
  9. assert.Equal(t, "http", port)
  10. host, port, err = net.SplitHostPort(":8000")
  11. require.NoError(t, err)
  12. assert.Equal(t, "", host)
  13. assert.Equal(t, "8000", port)
  14. host, port, err = net.SplitHostPort("1:8")
  15. require.NoError(t, err)
  16. assert.Equal(t, "1", host)
  17. assert.Equal(t, "8", port)
  1. // func TestSplitHostPort(t testing.T)
  2.  
  3. tests := []struct{
  4. give string
  5. wantHost string
  6. wantPort string
  7. }{
  8. {
  9. give: "192.0.2.0:8000",
  10. wantHost: "192.0.2.0",
  11. wantPort: "8000",
  12. },
  13. {
  14. give: "192.0.2.0:http",
  15. wantHost: "192.0.2.0",
  16. wantPort: "http",
  17. },
  18. {
  19. give: ":8000",
  20. wantHost: "",
  21. wantPort: "8000",
  22. },
  23. {
  24. give: "1:8",
  25. wantHost: "1",
  26. wantPort: "8",
  27. },
  28. }
  29.  
  30. for _, tt := range tests {
  31. t.Run(tt.give, func(t *testing.T) {
  32. host, port, err := net.SplitHostPort(tt.give)
  33. require.NoError(t, err)
  34. assert.Equal(t, tt.wantHost, host)
  35. assert.Equal(t, tt.wantPort, port)
  36. })
  37. }

Test tables make it easier to add context to error messages, reduce duplicatelogic, and add new test cases.

We follow the convention that the slice of structs is referred to as testsand each test case tt. Further, we encourage explicating the input and outputvalues for each test case with give and want prefixes.

  1. tests := []struct{
  2. give string
  3. wantHost string
  4. wantPort string
  5. }{
  6. // ...
  7. }
  8.  
  9. for _, tt := range tests {
  10. // ...
  11. }