2020-10-05

    科技2022-09-07  119

    Go语言TDD学习与实践

    1.TDD

    TDD是敏捷开发中的一项核心实践和技术,也是一种设计方法论。 即在开发功能代码之前,先编写单元测试用例代码,再依据测试代码编写能够通过测试的产品代码。 程序测试可以节省程序调试的时间,进而增强需求分析、提前编写测试框架,以节省后期迭代开发的成本。敏捷开发过程中的每个节点的代码都是某次测试后的分支版本,在重构或者添加新功能模块之后若有需要,可以回滚上个版本。 TDD的基本思路就是通过测试来推动整个开发的进行,但测试驱动开发并不只是单纯的测试工作,而是把需求分析,设计,质量控制量化的过程。 TDD的重要目的不仅仅是测试软件,测试工作保证代码质量仅仅是其中一部分,而且是在开发过程中帮助客户和程序员去除模棱两可的需求。TDD首先考虑使用需求(对象、功能、过程、接口等),主要是编写测试用例框架对功能的过程和接口进行设计,而测试框架可以持续进行验证。 TDD流程图:

    2.相关教程的学习总结

    https://studygolang.gitbook.io/learn-go-with-tests/go-ji-chu/iteration 下载相关代码,并按说明步骤进行实验 编写测试代码:

    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) } }

    这个测试代码,即测试函数Repeat是否能返回五个重复的输入值,但此时并没有定义Repeat函数,因此测试报错:

    随后遵循TDD原则,仅使代码可编译以检测测试是否通过:

    package iteration func Repeat(character string) string { return "" }

    得到测试结果:

    接下来按照测试代码的要求,重新编写Repeat函数,以实现要求:

    package iteration // Repeat returns character repeated 5 times. func Repeat(character string) string { var repeated string for i := 0; i < 5; i++ { repeated = repeated + character } return repeated }

    测试通过:

    重构:接下来在不改变代码功能的情况下优化代码,进行简化与可读性强化,一般可以通过复用、注释、调用等方式切入

    package iteration const repeatCount = 5 // Repeat returns character repeated 5 times. func Repeat(character string) string { var repeated string for i := 0; i < repeatCount; i++ { repeated += character } return repeated }

    主要的优化有:使repeat次数变量更易修改、简化for代码量,加入适当注释等。 基准测试:与测试步骤类似,但用途为对代码的时空性能进行量化评估,代码如下:

    func BenchmarkRepeat(b *testing.B) { for i := 0; i < b.N; i++ { Repeat("a") } }

    基准测试结果如下:

    即代码运行了6574340次,平均每次运行使用165ns,占用16B

    3. 完成教程“迭代”章节的练习

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

    这里需求发生了变化,新的需求要求调用者输入重复次数,输出指定重复次数的字符串,因此修改测试代码如下:

    func TestRepeat(t *testing.T) { repeated := Repeat("a", 5) expected := "aaaaa" if repeated != expected { t.Errorf("expected %q but got %q", expected, repeated) } }

    理所应当地测试结果失败,修改函数:

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

    测试通过,基准测试也进行了一次:

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

    即写一个示例函数,展示函数功能:

    func ExampleRepeat() { str := Repeat("b", 10) fmt.Println(str) //Output: bbbbbbbbbb }

    c 看一下 strings 包。找到你认为可能有用的函数,并对它们编写一些测试。投入时间学习标准库会慢慢得到回报。

    如对Compare函数进行测试:

    func TestRepeat(t *testing.T) { if strings.Compare("a", "b") == 0 { t.Errorf("") } if strings.Compare("a", "a") != 0 { t.Errorf("") } }

    测试通过

    4.按照TDD工作流程实现冒泡排序算法

    编写测试代码:

    package bubble import "testing" func TestRepeat(t *testing.T) { repeated := [9]int{1, 6, 3, 4, 8, 2, 7, 9, 5} expected := [9]int{1, 2, 3, 4, 5, 6, 7, 8, 9} if bubble(repeated) != expected { t.Errorf("expected %q but got %q", expected, repeated) } }

    首次测试失败(未定义测试对象),定义测试对象:

    package bubble func bubble(arr [9]int) [9]int { return arr }

    测试失败

    修改测试对象:

    package bubble func bubble(arr [9]int) [9]int { for i := 0; i < 8; i++ { for j := 0; j < 8; j++ { if arr[j] > arr[j+1] { temp := arr[j] arr[j] = arr[j+1] arr[j+1] = temp } } } return arr }

    测试通过:

    加入基准测试:

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

    基准测试结果:

    Processed: 0.008, SQL: 9