您的位置:首页 > 编程语言

译文:写在Go测试代码中例子(原文:Testable Examples in Go)

2016-05-05 13:32 513 查看
原文: https://blog.golang.org/examples

简介

Go自动生成的文档中有时你会看到代码例子,这些例子还可以通过点击网站上的Run按钮运行。而这些例子是从测试代码中提取出来的。



这些代码例子是具有可测性的,而带来的优点就是当API变化的时候,代码能够及时的同步。标准库中有很多库都包含代码例子,比如strings package

这篇文章将会教会你如何给一个库写例子代码。

例子代码

例子代码都是写在库的测试用例集里面的(以
_test.go
结尾的文件)。跟普通的测试函数不同的是,例子代码的函数不接受任何参数,命令函数命名以
Example
开头(普通测试函数是以
Test
开头的)

Go的官方例子代码库里可以找到一个 stringutil库,这个库实现了
Reverse
函数

package stringutil_test

import (
"fmt"

"github.com/golang/example/stringutil"
)

func ExampleReverse() {
fmt.Println(stringutil.Reverse("hello"))
// Output: olleh
}

上面这段代码应该可以在
example_test.go
里面找到。这段例子代码会自动在godoc中的Reverse函数的说明下找到。



运行该库的测试用例,我们可以看到相关的Example函数也跟着一起运行了。

$ go test -v
=== RUN TestReverse
--- PASS: TestReverse (0.00s)
=== RUN: ExampleReverse
--- PASS: ExampleReverse (0.00s)
PASS
ok      github.com/golang/example/stringutil    0.009s

输出的内容

程序是如何确定Example函数是否PASS呢?

当运行Example的测试用例的时候,测试框架捕获了其标准输出,并且用其跟注释中`Output: 开头的内容进行的对比,来确定是否调用成功

简单的修改下注释,就可以让这个测试用例FAIL了

func ExampleReverse() {
fmt.Println(stringutil.Reverse("hello"))
// Output: golly
}

重新运行后的效果

$ go test
--- FAIL: ExampleReverse (0.00s)
got:
olleh
want:
golly
FAIL

如果我们把Example里面的注释都删掉呢

func ExampleReverse() {
fmt.Println(stringutil.Reverse("hello"))
}

所有Example开头的函数虽然会写到文档中,但是不会作为测试程序执行了

$ go test -v
=== RUN TestReverse
--- PASS: TestReverse (0.00s)
PASS
ok      github.com/golang/example/stringutil    0.009s

这种情况适用于依赖外部环境,无法作为单侧用例执行的,比如依赖一个外部的网络服务。

例子函数名

Godoc是通过名字来将其关联到相应的函数的

func ExampleFoo()     // 作为Foo函数或者类型例子
func ExampleBar_Qux() // 作为Bar类型的Qux函数例子
func Example()        // 作为整个库的例子

通过这种规则,godoc将
ExampleReverse
函数对应到了
Reverse
这个函数

通过增加 下划线+小写字母开头的单词作为后缀,一个函数可以对应多个例子。例如

func ExampleReverse()
func ExampleReverse_second()
func ExampleReverse_third()

这3个函数对对应于
Reverse
这个函数。

更完整的例子

有些时候一个函数的例子已经无法说明一个函数该如何使用。

TODO 待翻译(困死了,先睡会)

For instance, to demonstrate the sort package we should show an implementation of sort.Interface. Since methods cannot be declared inside a function body, the example must include some context in addition to the example function.

To achieve this we can use a "whole file example." A whole file example is a file that ends in _test.go and contains exactly one example function, no test or benchmark functions, and at least one other package-level declaration. When displaying such examples godoc will show the entire file.

Here is a whole file example from the sort package:

package sort_test

import (
"fmt"
"sort"
)

type Person struct {
Name string
Age  int
}

func (p Person) String() string {
return fmt.Sprintf("%s: %d", p.Name, p.Age)
}

// ByAge implements sort.Interface for []Person based on
// the Age field.
type ByAge []Person

func (a ByAge) Len() int           { return len(a) }
func (a ByAge) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }

func Example() {
people := []Person{
{"Bob", 31},
{"John", 42},
{"Michael", 17},
{"Jenny", 26},
}

fmt.Println(people)
sort.Sort(ByAge(people))
fmt.Println(people)

// Output:
// [Bob: 31 John: 42 Michael: 17 Jenny: 26]
// [Michael: 17 Jenny: 26 Bob: 31 John: 42]
}

A package can contain multiple whole file examples; one example per file. Take a look at the sort package's source code to see this in practice.

结论

Godoc examples are a great way to write and maintain code as documentation. They also present editable, working, runnable examples your users can build on. Use them!

By Andrew Gerrand

相关文章

The cover story

Organizing Go code

Godoc: documenting Go code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  go test example