Unit testing Go code with mocks and dependency injection

Embedded Examples

Who reads manual pages?! Most users dread working through abstract descriptions of what a system does and prefer working examples of applications that can be copied directly and quickly adapted to individual needs. These example sections are usually hidden in the depths of the instructions, prompting many users to first scroll all the way to the bottom. Unfortunately, it's quite common that these application examples were neglected during development and don't work (anymore), because the developer changed the code and forgot to add the changes to the matching section on the manual page. This is remedied by Go's automatic manual page creator with examples that can be added to be continually tested in the unit test suite.

Figure 2 shows a web version of the manual page, featuring automatically generated and continually tested examples, which were embedded in the original Go code by the developer. The following command:

godoc -http=:6060
Figure 2: Examples show both sample code and standard output.

launches a webserver on port 6060. If you point a browser at http://localhost:6060/pkg, you can maneuver to the man page for the package. When a user clicks on the down arrow next to the word Example, this opens a section showing both the sample code and the results expected on the standard output.

The highlight is that this example was generated automatically from the test code of the package in Listing 7 by the godoc command above. And, on top of that, using go test, the sample code is actually run in the test suite, and its outcome is compared with what is documented – so the documentation always remains up to date!

Listing 7

example_test.go

01 package myhello
02
03 func ExampleSayHello() {
04     SayHello()
05     // Output: hello
06 }

The way this whole thing works is that Go can identify the ExampleSayHello() function in Listing 7 as an application example useful for the documentation. How? It simply sees the Example prefix of the function in the test file (suffix _test). The web version of the godoc command then puts it in place with the surrounding documentation, partly extracted from programmer comments and automatic code introspection. By convention, Go interprets the comment in line 5 of Listing 7 ("// Output: hello") as the example function's expected output, and go test executes ExampleSayHello() and checks whether hello actually appears on the standard output.

Along with the documentation automatically generated from code and comments in the library file in Listing 8, this results in self-checking documentation. It's a clear benefit for programmers who don't like to read instructions but just go directly to cut and paste. But software maintainers also benefit, as these checks make sure that embarrassing errors, such as the first application example in the documentation failing to run, no longer occur.

Listing 8

example.go

01 package myhello
02
03 import (
04     "fmt"
05 )
06
07 func SayHello() {
08     fmt.Println("hello")
09 }

The Author

Mike Schilli works as a software engineer in the San Francisco Bay area, California. Each month in his column, which has been running since 1997, he researches practical applications of various programming languages. If you email him at mailto:mschilli@perlmeister.com he will gladly answer any questions.

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy Linux Magazine

SINGLE ISSUES
 
SUBSCRIPTIONS
 
TABLET & SMARTPHONE APPS
Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

  • Perl: Cucumber

    The Cucumber test framework helps developers and product departments jointly formulate test cases, not as program code, but in plain English. The initially skeptical Perlmeister has acquired a taste for this.

  • Go on the Rasp Pi

    We show you how to create a Go web app that controls Raspberry Pi I/O.

  • Perl: Regression Tests

    With a test suite, you can fix bugs and add new features without ruining the existing codebase.

  • Perl: Test-Driven Development

    Test-driven development with a full-coverage regression test suite as a useful side effect promises code with fewer errors. Mike "Perlmeister" Schilli enters the same path of agility and encounters a really useful new CPAN module.

  • Rat Rac

    If program parts running in parallel keep interfering with each other, you may have a race condition. Mike Schilli shows how to instruct the Go compiler to detect these conditions and how to avoid them in the first place.

comments powered by Disqus
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters

Support Our Work

Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.

Learn More

News