DEV Community 👩‍💻👨‍💻

hzoltan
hzoltan

Posted on

Go: Provide automated tested examples for your documentation!

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"
}

Enter fullscreen mode Exit fullscreen mode

Add a function in your package's _test.go file:

func ExampleYourFunction() {
    result := YourFunction("some input")
    fmt.Println(result)
    // Output: wrong output
}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Now change it to "good output":

func ExampleYourFunction() {
    result := YourFunction("some input")
    fmt.Println(result)
    // Output: good output
}
Enter fullscreen mode Exit fullscreen mode

Now run it again:

$ go test -v       
=== RUN   ExampleYourFunction
--- PASS: ExampleYourFunction (0.00s)
PASS
ok      integers        0.366s
Enter fullscreen mode Exit fullscreen mode

Yey!

Detailed explanation

You can provide examples for your code which will be tested, you can see it with go test -v.

  1. Create a new directory integers
$ mkdir integers
Enter fullscreen mode Exit fullscreen mode
  1. Init our new go module (not required)
$ go mod init integers
Enter fullscreen mode Exit fullscreen mode
  1. 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
}

Enter fullscreen mode Exit fullscreen mode
  1. Examples are living along with the automated tests in the _test file, create a new integers_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
}

Enter fullscreen mode Exit fullscreen mode
  1. 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
Enter fullscreen mode Exit fullscreen mode

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!

  1. Fix the output and run your tests again:
func ExampleMultiply() {
    product := Multiply(3, 3)
    fmt.Println(product)
    // Output: 9
}
Enter fullscreen mode Exit fullscreen mode
$ go test -v
=== RUN   ExampleMultiply
-------- PASS: ExampleMultiply (0.00s)
PASS
ok      integers        0.880s
Enter fullscreen mode Exit fullscreen mode
  1. Now let's see how does this look in the documentation. Run godoc to see it troubleshooting:
$ godoc -http :8000
Enter fullscreen mode Exit fullscreen mode

Now navigate to the documentation: http://localhost:8000/pkg/integers/

alt text

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:

  1. I learned this from the Learn go with tests book, I highly recommend to read it!
  2. 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
Enter fullscreen mode Exit fullscreen mode

Top comments (2)

Collapse
shindakun profile image
Steve Layton

Nice post!

Collapse
hzoltan profile image
hzoltan Author

Hey Steve! Thanks for the feedback!

🌚 Life is too short to browse without dark mode