TDD实践报告

作业2: TDD实践报告

实验环境

操作系统:Mac OS

编译器:VScode

迭代章节练习

练习1

  • 修改测试代码,以便调用者可以指定字符重复的次数,然后修复代码

首先编写测试文件 repeat_test.go 代码和章节中给出的基本相同,只需要更改 Repeat() 函数中的参数为两个,一个是需要重复的字符串,另一个是重复的次数,代码如下

package iteration

import "testing"

func TestRepeat(t *testing.T) {
    
    
	repeated := Repeat("a", 4 )
	expected := "aaaaa"

	if repeated != expected {
    
    
		t.Errorf("expected '%q' but got '%q'", expected, repeated)
	}
}

首先运行测试代码,得到如下的结果

在这里插入图片描述

可以看到由于未编写需要测试的函数,所以编译会失败

开始编写 Repeat() 函数,函数需要两个参数,一个是 string 类型,另一个是int 类型,实现的方法也是用了 for 循环的形式,代码如下

package iteration

func Repeat(character string, count int) string {
    
    
	var ret string = ""
	for i := 0; i < count; i++ {
    
    
		ret += character
	}
	return ret
}

测试的代码写好后,可以直接在 VScode 中编译运行,或者在命令行中以 go test 命令进行测试,得到的结果如下所示

在这里插入图片描述

可以看到结果 FAIL ,原因是因为我在测试文件中选择了先测试 repeat 4次,所以得到的结果与期望的不一样,重新更改测试代码,便可以得到正确的结果,会显示 PASS 如下所示:

在这里插入图片描述

练习2

  • 写一个 ExampleRepeat 来完善你的函数文档

关于示例的用法,在前一章节:整数中提到过,直接在 repeat_test.go 中创建新的函数 ExampleRepeat ,此函数用于输出得到的结果(注意:由于需要进行输出所以在代码开始处需要导入 fmt 包),与后面的注释中的内容进行比较,如果相同则成功,否则失败,代码如下:

func ExampleRepeat() {
    
    
	s := Repeat("a", 5)
	fmt.Println(s)
	// Output: aaaa
}

可以看到我设置的迭代5次,而下面注释的输出是迭代了四次所以应该得到错误的结果,如下所示:

在这里插入图片描述

重新修改下面的注释使其迭代五次,检测的结果如下所示:

在这里插入图片描述

由结果可知,测试成功 PASS

练习3

  • 看一下 strings 包。找到你认为可能有用的函数,并对它们编写一些测试。投入时间学习标准库会慢慢得到回报。
  1. func Compare(a, b string) int 函数,此函数是用来比较前后字符串的字典序的大小,如果 a < b 则返回 -1;a = b 则返回0;a > b 则返回1,测试的代码文件为 compare_test.go
package iteration

import (
	"strings"
	"testing"
)

func TestCompare(t *testing.T) {
    
    
	ans := strings.Compare("h", "z")
	expected := -1

	if ans != expected {
    
    
		t.Errorf("expected '%d' but got '%d'", expected, ans)
	}
}

然后进行测试,得到的结果如下所示:

在这里插入图片描述

由结果可知测试成功

  1. func Count(s, substr string) int 函数,此函数是统计字符串 s 中包含子串 substr 的个数,然后返回该值,测试的代码文件为 count_test.go
package iteration

import (
	"strings"
	"testing"
)

func TestCount(t *testing.T) {
    
    
	ans := strings.Count("cheeze", "e")
	expected := 3

	if ans != expected {
    
    
		t.Errorf("expected '%d' but got '%d'", expected, ans)
	}
}

然后进行测试,得到的结果如下所示:

在这里插入图片描述

由结果可知,测试成功

  1. func ReplaceAll(s, old, new string) string 函数,此函数是在 s 字符串中用 new 字符串去替代所有出现的 old 字符串,测试的文件为 replace_test.go
package iteration

import (
	"strings"
	"testing"
)

func TestReplace(t *testing.T) {
    
    
	ans := strings.ReplaceAll("oink oink oink", "oink", "moo")
	expected := "moo moo moo"

	if ans != expected {
    
    
		t.Errorf("expected '%s' but got '%s'", expected, ans)
	}
}

然后进行测试,得到的结果如下所示:

在这里插入图片描述

由结果可知,测试成功

快排算法实现

算法介绍

快速排序(Quicksort)是对冒泡排序的一种改进。算法的主要步骤为:

  • 首先设定一个分界值,通过该分界值将数组分成左右两部分。

  • 将大于或等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边。此时,左边部分中各元素都小于或等于分界值,而右边部分中各元素都大于或等于分界值。

  • 然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理。

  • 重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当左、右两个部分各数据排序完成后,整个数组的排序也就完成了。

通过上述对于算法的描述,首先完成一个 main 函数,来测试一下快速排序是否成功实现,代码如下:

package main

import "fmt"

const MAXN = 10

var arr = []int{
    
    7, 4, 8, 5, 3, 6, 9, 1, 10, 2}

// 快速排序递归实现
func QuickSort(arr []int, l, r int) {
    
    
	pivot := arr[l] // 选取中间值
	pos := l        // 中间值的位置
	i, j := l, r

	for i <= j {
    
    
		for j >= pos && arr[j] >= pivot {
    
    
			j--
		}
		if j >= pos {
    
    
			arr[pos] = arr[j]
			pos = j
		}

		for i <= pos && arr[i] <= pivot {
    
    
			i++
		}
		if i <= pos {
    
    
			arr[pos] = arr[i]
			pos = i
		}
	}
	arr[pos] = pivot
	if pos-l > 1 {
    
    
		QuickSort(arr, l, pos-1)
	}
	if r-pos > 1 {
    
    
		QuickSort(arr, pos+1, r)
	}
}

func main() {
    
    
	QuickSort(arr, 0, len(arr)-1)
	for i := 0; i < MAXN; i++ {
    
    
		fmt.Printf("%d\t", arr[i])
	}
}

通过运行整个代码,可以看到结果如下:

在这里插入图片描述

先写测试

首先写一个测试文件 QuickSort_test.go ,但并不写 QuickSort.go文件,看看测试文件的输出

package Qsort

import "testing"

const MAXN = 10

var arr = []int{
    
    7, 4, 8, 5, 3, 6, 9, 1, 10, 2}

func TestQuickSort(t *testing.T) {
    
    
	QuickSort(arr, 0, MAXN-1)
	expected := []int{
    
    1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

	flag := true
	for i := 0; i < MAXN; i++ {
    
    
		if arr[i] != expected[i] {
    
    
			flag = false
		}
	}
	if flag == false {
    
    
		t.Errorf("expected ")
		for i := 0; i < MAXN; i++ {
    
    
			t.Errorf("%d\t", expected[i])
		}
		t.Errorf("but got")
		for i := 0; i < MAXN; i++ {
    
    
			t.Errorf("%d\t", arr[i])
		}
	}

}

写好代码后,直接运行,得到以下的结果

在这里插入图片描述

可以看到由于缺少被测试的文件,所以会编译出错

最少代码运行测试

开始写被测试的代码文件 QuickSort.go ,使得测试能够成功运行起来,所以直接写一个语法正确的空代码即可

package Qsort

// 快速排序递归实现
func QuickSort(arr []int, l, r int) {
    
    

}

写好代码后,进行测试,得到的输出结果如下所示

在这里插入图片描述

代码补全成功测试

先行测试结束后,将QuickSort.go 文件进行修改,修改后的代码为

package Qsort

// 快速排序递归实现
func QuickSort(arr []int, l, r int) {
    
    
	pivot := arr[l] // 选取中间值
	pos := l        // 中间值的位置
	i, j := l, r

	for i <= j {
    
    
		for j >= pos && arr[j] >= pivot {
    
    
			j--
		}
		if j >= pos {
    
    
			arr[pos] = arr[j]
			pos = j
		}

		for i <= pos && arr[i] <= pivot {
    
    
			i++
		}
		if i <= pos {
    
    
			arr[pos] = arr[i]
			pos = i
		}
	}
	arr[pos] = pivot
	if pos-l > 1 {
    
    
		QuickSort(arr, l, pos-1)
	}
	if r-pos > 1 {
    
    
		QuickSort(arr, pos+1, r)
	}
}

首先进行测试,将测试的代码中 expected 中的2改为3看看测试文件是否能检测出错,得到的结果如图所示

在这里插入图片描述

由上图可知测试文件能检测出来错误,然后进行正确的测试,得到的结果为
在这里插入图片描述
如上图所示,可以看到成功测试了,并且通过了,说明我设计的快速排序代码是正确的。

重构

由于原算法并没有太多需要修改的地方,所以在原代码的上方进行了注释

基准测试

在测试文件中写基准测试,使测试代码运行 b.N 次,并测试需要多长的时间,添加的代码如下所示

func BenchmarkQuickSort(b *testing.B) {
    
    
	for i := 0; i < b.N; i++ {
    
    
		var arrt = []int{
    
    7, 4, 8, 5, 3, 6, 9, 1, 10, 2}
		QuickSort(arrt, 0, MAXN-1)
	}
}

写好基准测试代码后,在命令行中输入命令 go test -bench=. 进行测试代码运行的时间,结果是如下所示

在这里插入图片描述
至此完成了全部的测试过程

github地址

代码传送门:传送门

总结

通过本次实验学会了测试的基本步骤,也理解TDD、重构、测试、基准测试等概念,并且进一步掌握了GO语言的一些用法啊,能够熟练的运用到代码编写中,在代码的编写中也遇到了一些困难,也是通过C语言学习网中对GO的学习才得以解决。

猜你喜欢

转载自blog.csdn.net/qq_43267773/article/details/108743281
TDD