Go’s Testable Examples under the hood

Hidden introduction to ast and parser packages

Golang’s toolchain implements feature called Testable Examples. If name doesn’t tell you much I strongly recommend to read first “Testable Examples in Go” as a gentle introduction. Throughput this post we’ll see what underpins the whole solution and how to build its simplified version.

Let’s see how Testable Examples work:

upper_test.go:

package main import (

"fmt"

"strings"

) func ExampleToUpperOK() {

fmt.Println(strings.ToUpper("foo"))

// Output: FOO

} func ExampleToUpperFail() {

fmt.Println(strings.ToUpper("bar"))

// Output: BAr

} > go test -v

=== RUN ExampleToUpperOK

--- PASS: ExampleToUpperOK (0.00s)

=== RUN ExampleToUpperFail

--- FAIL: ExampleToUpperFail (0.00s)

got:

BAR

want:

BAr

FAIL

exit status 1

FAIL github.com/mlowicki/sandbox 0.008s

Examples just like test functions are placed in xxx_test.go files but are prefixed with Example instead of Test. Command go test uses comments in special format (Output: something) and compare them against captured data, normally written to stdout. The same comments are used by other tools like godoc to enrich automatically generated documentation.

The question is how go test or godoc are able to extract data from dedicated comments? Is there any secret mechanism in the language making it possible? Or maybe everything can be achieved with well-known constructions?

It turns out that standard library ships elements (spread across few packages) related to parsing source code in Go itself. These tools produce abstract syntax trees and provide access i.e. to comments left by programmer.