内容简介:在指定的条件下,操作程序,发现程序错误对软件的组成单元进行测试,最小单位:函数
GoCommunity.png
How to write test with golang
- TDD(Test-Driven development) 测试驱动开发
- 内置的 testing 库 、 表格驱动、样本测试、TestMain
- 第三方:goconvey
- Monkey 猴子补丁
- 数据库 mock
- travisCI
- 代码覆盖率
TDD
- 快速实现功能
- 再设计和重构
软件测试
在指定的条件下,操作程序,发现程序错误
单元测试
对软件的组成单元进行测试,最小单位:函数
包含三个步骤:
- 指定输入
- 指定预期
- 函数结果和指定的预期比较
指标:
- 代码覆盖率:运行测试执行的代码占总代码的行数
testing 库的使用
// Hello ... func Hello() string { return "Hello World" }
// 传统测试 func TestHello(t *testing.T) { result := Hello() want := "Hello World" if result == want { t.Logf("Hello() = %v, want %v", result, want) } else { t.Errorf("Hello() = %v, want %v", result, want) } want2 := "Hello world" if result == want2 { t.Logf("Hello() = %v, want %v", result, want) } else { t.Errorf("Hello() = %v, want %v", result, want) } } // 表格驱动测试: 使用匿名结构体,逻辑更清晰 func TestHelloWithTable(t *testing.T) { tests := []struct { name string want string }{ // TODO: Add test cases. { name: "test for hello", want: "Hello World", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if got := Hello(); got != tt.want { t.Errorf("Hello() = %v, want %v", got, tt.want) } }) } }
运行:
// mode one go test // equal to : go test . 执行当前目录下的测试文件 // mode two go test ./.. // 加上路径参数,可以执行指定目录下的测试文件
样本测试:
func ExampleHello() { fmt.Println(Hello()) // Output: // Hello World }
TestMain:
包的测试运行之前执行
func TestMain(m *testing.M) { fmt.Println("Before ====================") code := m.Run() fmt.Println("End ====================") os.Exit(code) }
testing 包含下面几种方法:
- Log | Logf
- Error | ErrorF
- Fatal | FatalF
备注:
- 文件必须以 ...test.go 结尾
- 测试函数必须以 TestX... 开头,
X
可以是_
或者大写字母,不可以是小写字母或数字 - 参数:*testing.T
- 样本测试必须以 Example... 开头,输入使用注释的形式
- TestMain 每个包只有一个,参数为 *testing.M
覆盖率:
go test -cover go test -coverprofile=cover.out go tool cover -html=cover.out -o coverage.html
第三方:goconvey
- 支持断言
- 支持嵌套
- 完全兼容内置 testing
- 提供 web UI
func TestAdd_Two(t *testing.T) { Convey("test add", t, func() { Convey("0 + 0", func() { So(Add(0, 0), ShouldEqual, 0) }) Convey("-1 + 0", func() { So(Add(-1, 0), ShouldEqual, -1) }) }) } func TestFloatToString_Two(t *testing.T) { Convey("test float to string", t, func() { Convey("1.0/3.0", func() { result := FloatToString(1.0, 3.0) So(result, ShouldContainSubstring, "%") So(len(result), ShouldEqual, 6) So(result, ShouldEqual, "33.33%") }) }) }
goconvey // 启动 web 界面
Monkey 猴子补丁
- 函数打桩
- 过程打桩
- 方法打桩
// 函数 func main() { monkey.Patch(fmt.Println, func(a ...interface{}) (n int, err error) { s := make([]interface{}, len(a)) for i, v := range a { s[i] = strings.Replace(fmt.Sprint(v), "hell", "*bleep*", -1) } return fmt.Fprintln(os.Stdout, s...) }) fmt.Println("what the hell?") // what the *bleep*? }
// 方法 func main() { var d *net.Dialer // Has to be a pointer to because `Dial` has a pointer receiver monkey.PatchInstanceMethod(reflect.TypeOf(d), "Dial", func(_ *net.Dialer, _, _ string) (net.Conn, error) { return nil, fmt.Errorf("no dialing allowed") }) _, err := http.Get("http://google.com") fmt.Println(err) // Get http://google.com: no dialing allowed }
// 过程 guard := Patch(DestroyResource, func(_ string) { }) defer guard.Unpatch()
使用思路,被测函数中需要使用的其他依赖函数,进行打桩处理。
sqlmock
对 sql 的执行过程进行打桩。
- 创建模拟连接
- 编写 原生 sql 语句
- 编写 返回值 或者 错误信息
- 判断执行结果和预设的返回值
Reference
- gotests 自动生成测试代码,只需填写测试数据即可
- goconvey 第三方测试库,兼容 testing 库
- httpmock 接口模拟
- how to test with Go 参考文档
- monkey 猴子补丁
- sqlmock sqlmock
- how to test with Go 参考文档
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Beginning Google Maps API 3
Gabriel Svennerberg / Apress / 2010-07-27 / $39.99
This book is about the next generation of the Google Maps API. It will provide the reader with the skills and knowledge necessary to incorporate Google Maps v3 on web pages in both desktop and mobile ......一起来看看 《Beginning Google Maps API 3》 这本书的介绍吧!