作业要求
完成参考教程“迭代”章节的练习,理解TDD、重构、测试、基准测试等概念。自己选择一个算法如“快排”,模仿教程内容结构,写一个Go语言某算法实现TDD实践报告。
概念理解
TDD
TDD是测试驱动开发(Test-Driven Development)的英文简称。TDD的原理是在开发功能代码之前,先编写单元测试用例代码,测试代码确定需要编写什么产品代码。
重构
重构就是通过调整程序代码改善软件的质量、性能,使其程序的设计模式和架构更趋合理,提高软件的扩展性和维护性。
基准测试
基准测试是指通过设计科学的测试方法、测试工具和测试系统,实现对一类测试对象的某项性能指标进行定量的和可对比的测试。
快速排序的TDD实现
1. 先写测试
先写一个随机排序的数组,然后将其从小到大的排序写出作为期望输出。若实际输出和期望输出不一致则报错。
package qsort
import "testing"
func TestQuickSort(t *testing.T) {
arr := []int{1,5,9,7,3,6,4,8,2,0}
test:= qsort(arr, 0, 9)
expect := []int{0,1, 2, 3, 4, 5, 6, 7, 8,9}
for i := 0; i < 10; i++ {
if res[i] != expect[i] {
t.Errorf("Given an array [1,5,9,7,3,6,4,8,2,0]\nExpected %v\n but got %v\n", res, expect, arr2)
break
}
}
}
先尝试运行测试
发现qsort未定义
2. 先使用最少的代码来让失败的测试先跑起来
在同一文件夹下新建qsort.go文件,用最少的代码实现qsort且是失败的
package qsort
func qsort(arr [] int, low, high int) ([]int) {
return arr
}
运行测试
3. 把代码补充完整,使得它能够通过测试
先用冒泡排序实现qsort,让其通过测试
func QuickSort(arr [] int, low, high int) ([]int) {
for i := 0; i <= high-low; i++{
for j := low; j < high-1-i; j++{
if arr[j] > arr[j+1] {
arr[j], arr[j+1] = arr[j+1], arr[i]
}
}
}
return arr
}
运行测试
测试通过
4. 重构
利用快速排序算法替代冒泡排序算法,让程序的质量更高。
快速排序算法首先在数组中寻找一个基准,数组中小于基准的数在基准的一侧,大于基准的数在基准的另一侧,因此我们需要先对数组进行分区。
func partition(arr []int,low,high int)(int){
mid := arr[low]
i := low+1
for j:=low;j<=high;j++{
if arr[j]<mid{
arr[j],arr[i]=arr[i],arr[j]
i++
}
}
arr[low],arr[i-1] = arr[i-1],arr[low]
return i-1
}
快速排序是一种递归算法,每当需要排序的数组的长度大于一,则将其基准左侧和基准右侧分别进行快速排序。
func qsort(arr []int,low,high int){
if low<high{
mid := partition(arr,low,high)
qsort(arr,low,mid-1)
qsort(arr,mid+1,high)
}
}
运行测试
测试通过
5. 基准测试
在测试代码文件中增加基准测试:
func BenchmarkQsort(b *testing.B){
arr := []int{1,5,9,7,3,6,4,8,2,0}
for i:=0;i < b.N;i++{
qsort(arr,0,9)
}
}
testing.B 可使你访问隐性命名(cryptically named)b.N。
基准测试运行时,代码会运行 b.N 次,并测量需要多长时间。
代码运行的次数不会对你产生影响,测试框架会选择一个它所认为的最佳值,以便让你获得更合理的结果。
用 go test -bench=. 来运行基准测试。
基准测试结果:
基准测试通过