作业2: TDD实际报告
试验环境
操作系统:Mac OS
编译器:VScode
迭代章节练习
练习1
- 批改测试代码,以便调用者能够指定字符反复的次数,而后修复代码
首先编写测试文件 repeat_test.go
代码和章节中给出的基本相同,只须要更改 Repeat()
函数中的参数为两个,一个是须要反复的字符串,另一个是反复的次数,代码如下
package iterationimport "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 iterationfunc 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 包。找到你认为可能有用的函数,并对它们编写一些测试。投入工夫学习规范库会缓缓失去回报。
func Compare(a, b string) int
函数,此函数是用来比拟前后字符串的字典序的大小,如果 a < b 则返回 -1;a = b 则返回0;a > b 则返回1,测试的代码文件为compare_test.go
package iterationimport ( "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) }}
而后进行测试,失去的后果如下所示:
由后果可知测试胜利
func Count(s, substr string) int
函数,此函数是统计字符串 s 中蕴含子串 substr 的个数,而后返回该值,测试的代码文件为count_test.go
package iterationimport ( "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) }}
而后进行测试,失去的后果如下所示:
由后果可知,测试胜利
func ReplaceAll(s, old, new string) string
函数,此函数是在 s 字符串中用 new 字符串去代替所有呈现的 old 字符串,测试的文件为replace_test.go
package iterationimport ( "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 mainimport "fmt"const MAXN = 10var 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 Qsortimport "testing"const MAXN = 10var 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的学习才得以解决。