Golang TDD实践报告:快速排序Quick Sort

TDD是测试驱动开发(Test-Driven Development)的英文简称,是敏捷开发中的一项核心实践和技术,也是一种设计方法论。
TDD设计周期如下(假设项目需求已知):

①编写符合项目输入输出的一个测试
②尝试运行测试
③先使用最少的代码来让失败的测试先跑起来
④编写足够的代码以使测试通过
⑤重构编写完整的代码以提高效率
⑥基准测试

在之前的C/C++编程中学习了许多有用的算法,比如排序算法。
最近笔者在入门Golang的开发应用,在掌握基本语法后感觉还是缺少了些东西,于是想尝试通过TDD设计风格来逐步实现一个常用的排序算法——快速排序(Quick Sort)算法。

0.项目需求

项目需求:设计一个名为QuickSort的函数,实现快速排序算法。
用法:给定一个长度(如L=10)的整数数组,调用QuickSort函数将其排序为数值从小到大的数组。

1.编写符合项目输入输出的一个测试

创建文件夹quicksort,将其作为项目目录。
在 QuickSort_test.go 中:

package quicksort

import "testing"

func TestQuickSort(t *testing.T) {
	arr0 := []int{1, 9, 2, 8, 3, 7, 4, 6, 5, 0}
	arr1 := []int{1, 9, 2, 8, 3, 7, 4, 6, 5, 0}

	got := QuickSort(arr1, 0, 9)
	want := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

	for i := 0; i < 10; i++ {
		if got[i] != want[i] {
			t.Errorf("\n got %v\n want %v\n given %v", got, want, arr0)
			break
		}
	}
}

也上面的迭代可以改为更为简洁的形式,导入import "reflect"并使用reflect.DeepEqual(got, want)比较即可:

package quicksort

import (
	"reflect"
	"testing"
)

func TestQuickSort(t *testing.T) {
	arr0 := []int{1, 9, 2, 8, 3, 7, 4, 6, 5, 0}
	arr1 := []int{1, 9, 2, 8, 3, 7, 4, 6, 5, 0}

	got := QuickSort(arr1, 0, 9)
	want := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

	if !reflect.DeepEqual(got, want) {
		t.Errorf("\n got %v\n want %v\n given %v", got, want, arr0)
	}
}

2.尝试运行测试

在项目目录下,使用go test指令运行测试,报错信息如下:

[henryhzy@localhost quicksort]$ go test
# github.com/user/quicksort [github.com/user/quicksort.test]
./QuickSort_test.go:9:2: undefined: QuickSort
FAIL	github.com/user/quicksort [build failed]

3.先使用最少的代码来让失败的测试先跑起来

在 QuickSort.go 中:

package quicksort

func QuickSort(arr []int, l, r int) ([]int){
    return arr
}

再次在项目目录下,使用go test指令运行测试,报错信息如下:

[henryhzy@localhost quicksort]$ go test
--- FAIL: TestQuickSort (0.00s)
    QuickSort_test.go:14: 
         got [1 9 2 8 3 7 4 6 5 0]
         want [0 1 2 3 4 5 6 7 8 9]
         given [1 9 2 8 3 7 4 6 5 0]
FAIL
exit status 1
FAIL	github.com/user/quicksort	0.002s

4.编写足够的代码以使测试通过

在 QuickSort.go 中:

package quicksort

func QuickSort(arr []int, l, r int) []int {
	Sort(arr, l, r)
	return arr
}

func Sort(arr []int, l, r int) {
	if l >= r {
		return
	}

	i := Partition(arr, l, r)
	Sort(arr, l, i-1)
	Sort(arr, i+1, r)
}

func Partition(arr []int, l, r int) int {
	i, j, key := l, r, arr[l]

	for i < j {
		for i < j && arr[j] > key {
			j--
		}
		arr[i] = arr[j]

		for i < j && arr[i] < key {
			i++
		}
		arr[j] = arr[i]
	}

	arr[i] = key
	return i
}

在项目目录下,使用go test指令运行测试,提示正确的信息如下:

[henryhzy@localhost quicksort]$ go test
PASS
ok  	github.com/user/quicksort	0.002s

5.重构编写完整的代码以提高效率

考虑到每次递归调用Sort函数时,每个Sort函数都需要调用一次Partition函数,而事实上Partition函数可以融合到Sort函数中,从而减少函数调用的时间,提高了代码的运行效率。

在 QuickSort.go 中:

package quicksort

func QuickSort(arr []int, l, r int) []int {
	Sort(arr, l, r)
	return arr
}

func Sort(arr []int, l, r int) {
	if l >= r {
		return
	}

	i, j, key := l, r, arr[l]

	for i < j {
		for i < j && arr[j] > key {
			j--
		}
		if i<j {
			arr[i] = arr[j]
			i++
		}
		
		for i < j && arr[i] < key {
			i++
		}
		if i<j {
			arr[j] = arr[i]
			j--
		}
	}

	arr[i] = key
	Sort(arr, l, i-1)
	Sort(arr, i+1, r)
}

在项目目录下,使用go test指令运行测试,提示正确的信息如下:

[henryhzy@localhost quicksort]$ go test
PASS
ok  	github.com/user/quicksort	0.002s

6.基准测试

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

在项目目录下,使用“go test -bench=.”指令运行基准测试,其结果如下:

[henryhzy@localhost quicksort]$ go test -bench=.
goos: linux
goarch: amd64
pkg: github.com/user/quicksort
BenchmarkQuickSort 	 8373924	       162 ns/op
PASS
ok  	github.com/user/quicksort	1.505s
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值