go语言测试之TDD
一、TDD理解
TDD定义
TDD是测试驱动开发(Test-Driven Development)的英文简称,是敏捷开发中的一项核心实践和技术,也是一种设计方法论。TDD的原理是在开发功能代码之前,先编写单元测试用例代码,测试代码确定需要编写什么产品代码。TDD虽是敏捷方法的核心实践,但不只适用于XP(Extreme Programming),同样可以适用于其他开发方法和过程。
TDD的基本思路就是通过测试来推动整个开发的进行,但测试驱动开发并不只是单纯的测试工作,而是把需求分析,设计,质量控制量化的过程。其基本流程图如下:
基于TDD周期具体完成“迭代”章节教程
1、编写测试
在测试中我们测试Repeat函数,希望通过Repeat函数,返回一个字符串,该字符串包含5个传入的字符参数。
在iteration/repeat_test.go文件下编写测试代码如下:
package iteration
import "testing"
func TestRepeat(t *testing.T) {
repeated := Repeat("a")
expected := "aaaaa"
if repeated != expected {
t.Errorf("expected '%q' but got '%q'", expected, repeated)
}
}
2、运行测试得到失败的结果
由于没有定义Repeat函数,此时运行测试会报错,运行测试结果如下:
3、编写可以编译的实现
严格遵守TDD方法的步骤与原则,现在只需让代码可编译,这样你就可以检查测试用例能否通过。
在iteration/repeat.go文件下编写代码如下:
package iteration
func Repeat(character string) string {
return ""
}
4、运行测试得到失败的结果
在此已经定义了Repeat函数,接下来就可以进一步执行测试代码里面的具体内容,但是运行测试的结果也会错误,这是因为Repeat函数定义的问题。运行测试结果如下:
5、编写可以通过测试的实现
根据上一步的运行测试结果以及测试代码的要求,重新编写符合测试要求的Repeat函数,由于已经知道了测试代码的具体内容,这一步可以通过需求写出Repeat函数。
在iteration/repeat.go文件下重新编写代码如下:
package iteration
func Repeat(character string) string {
var repeated string
for i := 0; i < 5; i++ {
repeated = repeated + character
}
return repeated
}
6、运行测试得到成功的结果
对Repeat函数的重写满足了测试代码的需求,因此运行测试会得到成功的结果。运行测试结果如下:
7、重构
虽然代码repeat.go文件中的代码已经通过了测试,但是其代码的规范性和简洁性还是存在很多问题,所以需要我们对代码进行重构,重构代码要求在不改变代码的逻辑和功能的前提下,尽可能的简化代码。简化的目的有增强代码的可读性、加快代码的执行速度等等。常见的简化方法就是重用代码(将频繁使用的变量、常量以及函数另外定义出来,这样就可以在各个地方调用此变量、常量、函数即可)。在这里对repeat.go重构如下:
package iteration
const repeatCount = 5
func Repeat(character string) string {
var repeated string
for i := 0; i < repeatCount; i++ {
repeated += character
}
return repeated
}
基准测试(benchmarks)
基于TDD周期具体完成“迭代”章节的例子之后,还可以在此基础上编写基准测试。在 Go 中编写基准测试(benchmarks)是该语言的另一个一级特性,它与在TDD中的编写测试步骤非常相似。
在iteration/reoeat_test.go的原基础上添加如下基准测试的代码:
func BenchmarkRepeat(b *testing.B) {
for i := 0; i < b.N; i++ {
Repeat("a")
}
}
testing.B 可使你访问隐性命名(cryptically named)b.N。基准测试运行时,代码会运行 b.N 次,并测量需要多长时间。代码运行的次数不会对你产生影响,测试框架会选择一个它所认为的最佳值,以便让你获得更合理的结果。
用 go test -bench=. 来运行基准测试。(如果在 Windows Powershell 环境下使用 go test -bench=".")。运行测试结果如下:
二、完成该教程“迭代”章节的练习
修改测试代码,以便调用者可以指定字符重复的次数,然后修复代码
这里要求Repeat函数可以通过传入一个参数来指定字符重复的次数,我们修改测试代码如下:
package iteration
import "testing"
func TestRepeat(t *testing.T) {
repeated := Repeat("a", 6)
expected := "aaaaaa"
if repeated != expected {
t.Errorf("expected %q but got %q", expected, repeated)
}
}
由于Repeat函数的参数发生改变,运行测试会得到失败的结果。测试结果如下:
修改主代码使得测试通过,代码修改如下:
package iteration
//Repeat a string with
func Repeat(character string, Readcount int) string {
var repeated string
for i := 0; i < Readcount; i++ {
repeated += character
}
return repeated
}
此时运行测试会得到成功的结果。运行测试如下:
写一个 ExampleRepeat 来完善你的函数文档
为了完善函数文档,我们还需要写一个示例测试。在repeat_test.go文件里面加入一个示例测试函数ExampleRepeat,该函数代码如下:
func ExampleRepeat() {
str := Repeat("b", 10)
fmt.Println(str)
//Output: bbbbbbbbbb
}
运行测试结果如下:
这表明测试函数和示例测试函数都执行成功。此时查看函数文档,发现该函数文档已经包含示例测试部分。
看一下 strings 包。找到你认为可能有用的函数,并对它们编写一些测试
查看strings包文档,部分函数如下:
对Compare、ToLower函数进行编写应用测试,测试代码可简单写成如下:
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Println("compare:", strings.Compare("a", "b")) //Output: -1
fmt.Println("tolower:", strings.ToLower("ABC")) // Output: abc
}
运行测试代码得到的结果如下:
三、TDD应用:go语言实现冒泡排序算法
基于TDD周期完成冒泡排序算法
1、编写测试
在BubbleSort/BubbleSort_test.go文件下编写测试代码如下:
package BubbleSort
import (
"testing"
)
func TestBubbleSort(t *testing.T) {
arr := [10]int{
7, 6, 3, 9, 5, 0, 1, 4, 2, 8}
sorted := BubbleSort(arr)
expected := [10]int{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
for i := 0; i < 10; i++ {
if sorted[i] != expected[i] {
t.Errorf("expected %v but got %v", expected, sorted)
}
}
}
2、运行测试得到失败的结果
由于没有定义BubbleSortt函数,此时运行测试会报错,运行测试结果如下:
3、编写可以编译的实现
严格遵守TDD方法的步骤与原则,现在只需让代码可编译,这样你就可以检查测试用例能否通过。
在BubbleSort/BubbleSort.go文件下编写代码如下:
package BubbleSort
func BubbleSort(arr [10]int) [10]int {
return arr
}
4、运行测试得到失败的结果
在此已经定义了BubbleSort函数,接下来就可以进一步执行测试代码里面的具体内容,但是运行测试的结果也会错误,这是因为BubbleSortt函数定义的问题。运行测试结果如下:
5、编写可以通过测试的实现
根据上一步的运行测试结果以及测试代码的要求,重新编写符合测试要求的BubbleSort函数,由于已经知道了测试代码的具体内容,这一步可以通过需求写出BubbleSort函数。
在BubbleSort/BubbleSort.go文件下重新编写代码如下:
package BubbleSort
//BubbleSort sort a array
func BubbleSort(arr [10]int) [10]int {
for i := 0; i < 9; i++ {
for j := 0; j < 9-i; j++ {
if arr[j] > arr[j+1] {
temp := arr[j]
arr[j] = arr[j+1]
arr[j+1] = temp
}
}
}
return arr
}
6、运行测试得到成功的结果
对BubbleSort函数的重写满足了测试代码的需求,因此运行测试会得到成功的结果。运行测试结果如下:
7、重构
根据前面提到的方法,对BubbleSort.go重构如下:
package BubbleSort
const count = 10
//BubbleSort sort a array
func BubbleSort(arr [10]int) [10]int {
for i := 0; i < count-1; i++ {
for j := 0; j < count-1-i; j++ {
if arr[j] > arr[j+1] {
temp := arr[j]
arr[j] = arr[j+1]
arr[j+1] = temp
}
}
}
return arr
}
基准测试(benchmarks)
在BubbleSort/BubbleSort.go的原基础上添加如下基准测试的代码:
func BenchmarkBubbleSort(b *testing.B) {
for i := 0; i < b.N; i++ {
arr := [10]int{
7, 6, 3, 9, 5, 0, 1, 4, 2, 8}
BubbleSort(arr)
}
}
用 go test -bench=. 来运行基准测试。(如果在 Windows Powershell 环境下使用 go test -bench=".")。运行测试结果如下:
来源:oschina
链接:https://my.oschina.net/u/4377109/blog/4647490