kota's memex

mocking interfaces coverage quality fuzzing

A file that ends in _test.go will be built and used with the go test tool. Test functions have the following form:

func Test(t *testing.T) {
  err := Name()
  if err != nil{
    t.Errorf("TestName failed: %v", err)
  }
}

Name must begin with a capital letter and typically corresponds to the function in your package the test is for. t provides several methods for logging and reporting errors. You may also create "helper" functions in your test files which are used by tests but not executed by go test on their own. When developing a package it's good practice to write tests alongside your implementation rather than using a main function.

table driven

func TestSplit(t *testing.T) {
    type test struct {
        input string
        sep   string
        want  []string
    }

    tests := []test{
        {input: "a/b/c", sep: "/", want: []string{"a", "b", "c"}},
        {input: "a/b/c", sep: ",", want: []string{"a/b/c"}},
        {input: "abc", sep: "/", want: []string{"abc"}},
    }

    for _, tc := range tests {
        got := Split(tc.input, tc.sep)
        if !reflect.DeepEqual(tc.want, got) {
            t.Fatalf("expected: %v, got: %v", tc.want, got)
        }
    }
}

all

go test all This will test your module and all dependencies including standard lib ones. This can be used to validate that the exact versions of all your dependencies are compatible.

deep equality

https://github.com/google/go-cmp

This package makes it easy to compare structs, slices, and even print a diff if they do not match.

comparing unexported fields

By default go-cmp will panic if you compare types with unexported fields. They cannot be checked and thus you can't know for sure they're the same. In most cases they should "behave" the same as those fields are unexported for a reason. Most commonly this will happen if you compare two regexp.Regex types. In general the best solution is to create a custom comparer option and give that to cmp.Equal or cmp.Diff:

regexComparer := cmp.Comparer(func(x, y *regexp.Regexp) bool {
  return x.String() == y.String()
})

if diff := cmp.Diff(want, got, regexComparer); diff != "" {
  t.Errorf("TestOptions() mismatch (-want +got):\n%s", diff)
}

Worst case scenario there's also an AllowUnexported option that takes a type and will ignore unexported fields for that type.

race testing

Enabling the race detector will increase the overall running time of your tests, but it can be helpful as a pre-commit test:
$ go test -race ./...

fuzzing

https://github.com/dvyukov/go-fuzz

io.Writer /dev/null

You can discard io.Writer data using io.Discard. In older go versions it was in ioutil. It's a writer that simply discards its input. Perfect for testing.