golang测试技术
golang测试技术
一、基础测试技术 1、测试Go代码 Go语言内置测试框架。 内置的测试框架通过testing包以及go test命令来提供测试功能。 下面是一个完整的测试strings.Index函数的完整测试文件: //strings_test.go (这里样例代码放入strings_test.go文件中) import ( func TestIndex(t *testing.T) { $go test -v strings_test.go go test的-v选项是表示输出详细的执行信息。 将代码中的want常量值修改为3,我们制造一个无法通过的测试: $go test -v strings_test.go 2、表驱动测试 Golang的struct字面值(struct literals)语法让我们可以轻松写出表驱动测试。 package strings_test func TestIndex(t *testing.T) { 3、T结构 *testing.T参数用于错误报告: t.Errorf("got bar = %v,want %v",want) 也可以用于enable并行测试(parallet test): 控制一个测试是否运行: if runtime.GOARCH == "arm" { 4、运行测试 我们用go test命令来运行特定包的测试。 默认执行当前路径下包的测试代码。 $ go test $ go test -v 要运行工程下的所有测试,我们执行如下命令: $ go test github.com/nf/… 标准库的测试: 注:假设strings_test.go的当前目录为testgo,在testgo目录下执行go test都是OK的。但如果我们切换到testgo的上一级目录执行go test,我们会得到什么结果呢? $go test testgo 提示找不到testgo这个包,go test后面接着的应该是一个包名,go test会在GOROOT和GOPATH下查找这个包并执行包的测试。 5、测试覆盖率 go tool命令可以报告测试覆盖率统计。 我们在testgo下执行go test -cover,结果如下: go build _/Users/tony/Test/Go/testgo: no buildable Go source files in /Users/tony/Test/Go/testgo 显然通过cover参数选项计算测试覆盖率不仅需要测试代码,还要有被测对象(一般是函数)的源码文件。 我们将目录切换到$GOROOT/src/pkg/strings下,执行go test -cover: $go test -v -cover go test可以生成覆盖率的profile文件,这个文件可以被go tool cover工具解析。 在$GOROOT/src/pkg/strings下面执行: $ go test -coverprofile=cover.out 会再当前目录下生成cover.out文件。 查看cover.out文件,有两种方法: a) cover -func=cover.out $sudo go tool cover -func=cover.out b) 可视化查看 执行go tool cover -html=cover.out命令,会在/tmp目录下生成目录coverxxxxxxx,比如/tmp/cover404256298。目录下有一个 coverage.html文件。用浏览器打开coverage.html,即可以可视化的查看代码的测试覆盖情况。 关于go tool的cover命令,我的go version go1.3 darwin/amd64默认并不自带,需要通过go get下载。 $sudo GOPATH=/Users/tony/Test/GoToolsProjects go get code.google.com/p/go.tools/cmd/cover 下载后,cover安装在$GOROOT/pkg/tool/darwin_amd64下面。 二、高级测试技术 1、一个例子程序 outyet是一个web服务,用于宣告某个特定Go版本是否已经打标签发布了。其获取方法: go get github.com/golang/example/outyet 注: 2、测试Http客户端和服务端 net/http/httptest包提供了许多帮助函数,用于测试那些发送或处理Http请求的代码。 3、httptest.Server httptest.Server在本地回环网口的一个系统选择的端口上listen。它常用于端到端的HTTP测试。 type Server struct { // TLS is the optional TLS configuration,populated with a new config // Config may be changed after calling NewUnstartedServer and func NewServer(handler http.Handler) *Server func (*Server) Close() error 4、httptest.Server实战 下面代码创建了一个临时Http Server,返回简单的Hello应答: ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter,r *http.Request) { res,err := http.Get(ts.URL) greeting,err := ioutil.ReadAll(res.Body) fmt.Printf("%s",greeting) 5、httptest.ResponseRecorder httptest.ResponseRecorder是http.ResponseWriter的一个实现,用来记录变化,用在测试的后续检视中。 type ResponseRecorder struct { 6、httptest.ResponseRecorder实战 向一个HTTP handler中传入一个ResponseRecorder,通过它我们可以来检视生成的应答。 handler := func(w http.ResponseWriter,r *http.Request) { req,err := http.NewRequest("GET","http://example.com/foo",nil) w := httptest.NewRecorder() fmt.Printf("%d – %s",w.Code,w.Body.String()) 7、竞争检测(race detection) 当两个goroutine并发访问同一个变量,且至少一个goroutine对变量进行写操作时,就会发生数据竞争(data race)。 为了协助诊断这种bug,Go提供了一个内置的数据竞争检测工具。 通过传入-race选项,go tool就可以启动竞争检测。 $ go test -race mypkg // to test the package 注:一个数据竞争检测的例子 例子代码: //testrace.go package main import "fmt" func main() { for { $go run -race testrace.go Previous write by main goroutine: Goroutine 5 (running) created at: 8、测试并发(testing with concurrency) 当测试并发代码时,总会有一种使用sleep的冲动。大多时间里,使用sleep既简单又有效。 但大多数时间不是”总是“。 我们可以使用Go的并发原语让那些奇怪不靠谱的sleep驱动的测试更加值得信赖。 9、使用静态分析工具vet查找错误 vet工具用于检测代码中程序员犯的常见错误: 使用方法: 10、从内部测试 golang中大多数测试代码都是被测试包的源码的一部分。这意味着测试代码可以访问包种未导出的符号以及内部逻辑。就像我们之前看到的那样。 注:比如$GOROOT/src/pkg/path/path_test.go与path.go都在path这个包下。 11、从外部测试 有些时候,你需要从被测包的外部对被测包进行测试,比如测试代码在package foo_test下,而不是在package foo下。 这样可以打破依赖循环,比如: – testing包使用fmt 12、Mocks和fakes 通过在代码中使用interface,Go可以避免使用mock和fake测试机制。 例如,如果你正在编写一个文件格式解析器,不要这样设计函数: func Parser(f *os.File) error 作为替代,你可以编写一个接受interface类型的函数: func Parser(r io.Reader) error 和bytes.Buffer、strings.Reader一样,*os.File也实现了io.Reader接口。 13、子进程测试 有些时候,你需要测试的是一个进程的行为,而不仅仅是一个函数。例如: func Crasher() { 为了测试上面的代码,我们将测试程序本身作为一个子进程进行测试: func TestCrasher(t *testing.T) {
摘自:http://itindex.net/detail/51483-golang-%E6%B5%8B%E8%AF%95-%E6%8A%80%E6%9C%AF
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |