TL;DR:
You can provide example usage of your code which will be tested with go test -v
. Imagine you have this really cool function:
// YourFunction will return "good output" no matter what.
func YourFunction(someInput string) string {
return "good output"
}
Add a function in your package's _test.go
file:
func ExampleYourFunction() {
result := YourFunction("some input")
fmt.Println(result)
// Output: wrong output
}
Notice the Example*
prefix of the function name. Now if you run go test -v
it should break, because the output is wrong!
$ go test -v
=== RUN ExampleYourFunction
--- FAIL: ExampleYourFunction (0.00s)
got:
good output
want:
wrong output
FAIL
exit status 1
FAIL example 0.978s
Now change it to "good output":
func ExampleYourFunction() {
result := YourFunction("some input")
fmt.Println(result)
// Output: good output
}
Now run it again:
$ go test -v
=== RUN ExampleYourFunction
--- PASS: ExampleYourFunction (0.00s)
PASS
ok integers 0.366s
Yey!
Detailed explanation
You can provide examples for your code which will be tested, you can see it with go test -v
.
- Create a new directory
integers
$ mkdir integers
- Init our new go module (not required)
$ go mod init integers
- Create a new file
integers.go
and put this function inside which we will test (I recommend you to type it instead of copy just for the sake of exercising your muscle memory)
package integers
// Multiply takes two integers and returns their product
func Multiply(x, y int) int {
return x * y
}
- Examples are living along with the automated tests in the
_test
file, create a newintegers_test.go
file and type your example for the function:
package integers
import (
"fmt"
)
func ExampleMultiply() {
product := Multiply(3, 3)
fmt.Println(product)
// Output: 8
}
- You may already noticed but the
// Output: 8
is not the result this function will return, this is exactly what we wanted: to have something that breaks. Let's check it ourselves:
$ go test -v
=== RUN ExampleMultiply
--- FAIL: ExampleMultiply (0.00s)
got:
9
want:
8
FAIL
exit status 1
FAIL integers 0.878s
We intentionally implemented it in a way to actually see it fail, but normally after a refactor you simply run your tests and go test
will take care about the examples you provided. Now let's correct our mistake!
- Fix the output and run your tests again:
func ExampleMultiply() {
product := Multiply(3, 3)
fmt.Println(product)
// Output: 9
}
$ go test -v
=== RUN ExampleMultiply
--- PASS: ExampleMultiply (0.00s)
PASS
ok integers 0.880s
- Now let's see how does this look in the documentation. Run godoc to see it troubleshooting:
$ godoc -http :8000
Now navigate to the documentation: http://localhost:8000/pkg/integers/
Amazing! Right? You have an example which is also a test, and even if you intentionally implement API breaking changes (which we obviously try to avoid) than you will see that you have to change your documentation.
I hope you enjoyed it! Here are the sources:
- I learned this from the Learn go with tests book, I highly recommend to read it!
- If you are interested in more detailed examples, check The Go Blog: Testable Examples in Go
Troubleshooting
In Go 1.14+ godoc is no longer included, you may have to install it directly:
$ go get golang.org/x/tools/cmd/godoc
Top comments (2)
Nice post!
Hey Steve! Thanks for the feedback!