go语言测试之TDD

   日期:2020-09-24     浏览:157    评论:0    
核心提示:go语言测试之TDD一、TDD理解TDD定义基于TDD周期具体完成“迭代”章节教程基准测试(benchmarks)二、完成该教程“迭代”章节的练习三、TDD应用:go语言实现冒泡排序算法。一、TDD理解TDD定义TDD是测试驱动开发(Test-Driven Development)的英文简称,是敏捷开发中的一项核心实践和技术,也是一种设计方法论。TDD的原理是在开发功能代码之前,先编写单元测试用例代码,测试代码确定需要编写什么产品代码。TDD虽是敏捷方法的核心实践,但不只适用于XP(Extreme P

go语言测试之TDD

      • 一、TDD理解
        • TDD定义
        • 基于TDD周期具体完成“迭代”章节教程
        • 基准测试(benchmarks)
      • 二、完成该教程“迭代”章节的练习
        • 修改测试代码,以便调用者可以指定字符重复的次数,然后修复代码
        • 写一个 ExampleRepeat 来完善你的函数文档
        • 看一下 strings 包。找到你认为可能有用的函数,并对它们编写一些测试
      • 三、TDD应用:go语言实现冒泡排序算法
        • 基于TDD周期完成冒泡排序算法
        • 基准测试(benchmarks)

一、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=".")。运行测试结果如下:


 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服