github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/blog/content/examples.article (about)

     1  Testable Examples in Go
     2  7 May 2015
     3  Tags: godoc, testing
     4  
     5  Andrew Gerrand
     6  
     7  * Introduction
     8  
     9  Godoc [[http://golang.org/pkg/testing/#hdr-Examples][examples]] are snippets of
    10  Go code that are displayed as package documentation and that are verified by
    11  running them as tests.
    12  They can also be run by a user visiting the godoc web page for the package
    13  and clicking the associated "Run" button.
    14  
    15  Having executable documentation for a package guarantees that the information
    16  will not go out of date as the API changes.
    17  
    18  The standard library includes many such examples
    19  (see the [[http://golang.org/pkg/strings/#Contains][`strings` package]],
    20  for instance).
    21  
    22  This article explains how to write your own example functions.
    23  
    24  * Examples are tests
    25  
    26  Examples are compiled (and optionally executed) as part of a package's test
    27  suite.
    28  
    29  As with typical tests, examples are functions that reside in a package's
    30  `_test.go` files.
    31  Unlike normal test functions, though, example functions take no arguments
    32  and begin with the word `Example` instead of `Test`.
    33  
    34  The [[https://godoc.org/github.com/golang/example/stringutil/][`stringutil` package]]
    35  is part of the [[https://github.com/golang/example][Go example repository]].
    36  Here's an example that demonstrates its `Reverse` function:
    37  
    38  	package stringutil_test
    39  
    40  	import (
    41  		"fmt"
    42  
    43  		"github.com/golang/example/stringutil"
    44  	)
    45  
    46  	func ExampleReverse() {
    47  		fmt.Println(stringutil.Reverse("hello"))
    48  		// Output: olleh
    49  	}
    50  
    51  This code might live in `example_test.go` in the `stringutil` directory.
    52  
    53  Godoc will present this example alongside the `Reverse` function's documentation:
    54  
    55  .image examples/reverse.png
    56  
    57  Running the package's test suite, we can see the example function is executed
    58  with no further arrangement from us:
    59  
    60  	$ go test -v
    61  	=== RUN TestReverse
    62  	--- PASS: TestReverse (0.00s)
    63  	=== RUN: ExampleReverse
    64  	--- PASS: ExampleReverse (0.00s)
    65  	PASS
    66  	ok  	github.com/golang/example/stringutil	0.009s
    67  
    68  * Output comments
    69  
    70  What does it mean that the `ExampleReverse` function "passes"?
    71  
    72  As it executes the example,
    73  the testing framework captures data written to standard output
    74  and then compares the output against the example's "Output:" comment.
    75  The test passes if the test's output matches its output comment.
    76  
    77  To see a failing example we can change the output comment text to something
    78  obviously incorrect
    79  
    80  	func ExampleReverse() {
    81  		fmt.Println(stringutil.Reverse("hello"))
    82  		// Output: golly
    83  	}
    84  
    85  and run the tests again:
    86  
    87  	$ go test
    88  	--- FAIL: ExampleReverse (0.00s)
    89  	got:
    90  	olleh
    91  	want:
    92  	golly
    93  	FAIL
    94  
    95  If we remove the output comment entirely
    96  
    97  	func ExampleReverse() {
    98  		fmt.Println(stringutil.Reverse("hello"))
    99  	}
   100  
   101  then the example function is compiled but not executed:
   102  
   103  	$ go test -v
   104  	=== RUN TestReverse
   105  	--- PASS: TestReverse (0.00s)
   106  	PASS
   107  	ok  	github.com/golang/example/stringutil	0.009s
   108  
   109  Examples without output comments are useful for demonstrating code that cannot
   110  run as unit tests, such as that which accesses the network, 
   111  while guaranteeing the example at least compiles.
   112  
   113  
   114  * Example function names
   115  
   116  Godoc uses a naming convention to associate an example function with a
   117  package-level identifier.
   118  
   119  	func ExampleFoo()     // documents the Foo function or type
   120  	func ExampleBar_Qux() // documents the Qux method of type Bar
   121  	func Example()        // documents the package as a whole
   122  
   123  Following this convention, godoc displays the `ExampleReverse` example
   124  alongside the documentation for the `Reverse` function.
   125  
   126  Multiple examples can be provided for a given identifier by using a suffix
   127  beginning with an underscore followed by a lowercase letter.
   128  Each of these examples documents the `Reverse` function:
   129  
   130  	func ExampleReverse()
   131  	func ExampleReverse_second()
   132  	func ExampleReverse_third()
   133  
   134  
   135  * Larger examples
   136  
   137  Sometimes we need more than just a function to write a good example.
   138  
   139  For instance, to demonstrate the [[https://golang.org/pkg/sort/][`sort` package]]
   140  we should show an implementation of `sort.Interface`. 
   141  Since methods cannot be declared inside a function body, the example must
   142  include some context in addition to the example function.
   143  
   144  To achieve this we can use a "whole file example."
   145  A whole file example is a file that ends in `_test.go` and contains exactly one
   146  example function, no test or benchmark functions, and at least one other
   147  package-level declaration.
   148  When displaying such examples godoc will show the entire file.
   149  
   150  Here is a whole file example from the `sort` package:
   151  
   152  	package sort_test
   153  
   154  	import (
   155  		"fmt"
   156  		"sort"
   157  	)
   158  
   159  	type Person struct {
   160  		Name string
   161  		Age  int
   162  	}
   163  
   164  	func (p Person) String() string {
   165  		return fmt.Sprintf("%s: %d", p.Name, p.Age)
   166  	}
   167  
   168  	// ByAge implements sort.Interface for []Person based on
   169  	// the Age field.
   170  	type ByAge []Person
   171  
   172  	func (a ByAge) Len() int           { return len(a) }
   173  	func (a ByAge) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
   174  	func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }
   175  
   176  	func Example() {
   177  		people := []Person{
   178  			{"Bob", 31},
   179  			{"John", 42},
   180  			{"Michael", 17},
   181  			{"Jenny", 26},
   182  		}
   183  
   184  		fmt.Println(people)
   185  		sort.Sort(ByAge(people))
   186  		fmt.Println(people)
   187  
   188  		// Output:
   189  		// [Bob: 31 John: 42 Michael: 17 Jenny: 26]
   190  		// [Michael: 17 Jenny: 26 Bob: 31 John: 42]
   191  	}
   192  
   193  A package can contain multiple whole file examples; one example per file.
   194  Take a look at the [[https://golang.org/src/sort/][`sort` package's source code]]
   195  to see this in practice.
   196  
   197  * Conclusion
   198  
   199  Godoc examples are a great way to write and maintain code as documentation.
   200  They also present editable, working, runnable examples your users can build on.
   201  Use them!