Gotcha: testable examples in Go need an output comment

Featured image for sharing metadata for article

One thing I really like about building libraries in Go is that you can create testable examples as a first-class citizen of the testing framework. This allows writing example code in the repository in a way that can make sure that expected use cases are always valid and do not break, but because it's annotated as an example test case, it then gets surfaced in documentation as examples.

For instance, we can see the below code which shows how to parse some HTTP Accept headers and the resulting response when printed out to stdout:

// source via https://gitlab.com/jamietanna/content-negotiation-go/blob/299506d7f0487fefb9e2f1f828c7c306cbe211f9/acceptheader_test.go#L38-47
func ExampleParseAcceptHeaders() {
	parsed := contentnegotiation.ParseAcceptHeaders("text/html", "application/json")
	for _, mt := range parsed {
		fmt.Println(mt.String())
	}

	// output:
	// text/html
	// application/json
}

One thing you'll notice is that we've got this output line, which checks what output is returned from the example.

This is the crux of this post - if you don't have this output: line, your test will not be executed, and although it'll be compiled, it will never execute in your tests.

I found this when working through a few internal libraries, and noticed that by changing functionality in the tests - that were designed to make them fail - I saw no errors.

The solution is to make sure that you're always asserting on the output: of an example test, but trying to remember that all the time is difficult, so I've raised this upstream at golangci-lint as something we may want to surface in linting. And lo and behold, someone has already prepared a check for it - Open Source is great!

An additional gotcha is that you need to make sure that your comments have a newline between them - for instance the following won't work:

func ExampleParseAcceptHeaders() {
	parsed := contentnegotiation.ParseAcceptHeaders("text/html", "application/json")
	for _, mt := range parsed {
		fmt.Println(mt.String())
	}

	// this won't actually work, because the output is inside another command - this needs a newline breaking the comments
	// output:
	// text/html
	// application/json
}

Written by Jamie Tanna's profile image Jamie Tanna on , and last updated on .

Content for this article is shared under the terms of the Creative Commons Attribution Non Commercial Share Alike 4.0 International, and code is shared under the Apache License 2.0.

#go #testing #blogumentation.

Also on:

This post was filed under articles.

Interactions with this post

Interactions with this post

Below you can find the interactions that this page has had using WebMention.

Have you written a response to this post? Let me know the URL:

Do you not have a website set up with WebMention capabilities? You can use Comment Parade.