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=".")。运行测试结果如下:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_45960131/article/details/108721261