服务计算 作业二 TDD实践

本文介绍了TDD(测试驱动开发)的概念、优势及实践步骤,通过Go语言展示了从编写测试用例开始,逐步实现 Repeat 函数和 BubbleSort 算法的过程,强调了小步前进、重构和基准测试的重要性。同时,文章还包含了对strings包中常见函数的测试用例编写。
摘要由CSDN通过智能技术生成

对TDD的理解

什么是TDD

TDD是测试驱动开发(Test-Driven Development),是敏捷开发中的一项核心实践和技术,也是一种设计方法论。
TDD的原理是在开发功能代码之前,先编写单元测试用例代码,测试代码确定需要编写什么产品代码。TDD虽是敏捷方法的核心实践,但不只适用于XP(Extreme Programming),同样可以适用于其他开发方法和过程。

图片来自简书用户SeabornLee

TDD的优势

提前澄清需求
先写测试可以帮助我们去思考需求,并提前澄清需求细节,而不是代码写到一半才发现不明确的需求。

降低开发者负担
通过明确的流程,让我们一次只关注一个点,思维负担更小。

测试驱动
即利用测试来驱动开发,是TDD的核心。要实现某个功能,要编写某个类或某个函数,应首先编写测试代码,明确这个类、这个函数如何使用,如何测试,然后在对其进行设计、编码。

小步前进
软件开发是复杂性非常高的工作,小步前进是降低复杂性的好办法。

参考教程的步骤实践

1. 测试

首先编写测试文件iteration/repeat_test.go:

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(iteration/repeat.go)函数,让测试能够先跑起来

package iteration

// Repeat is a function
func Repeat(character string) string {
	return ""
}

接下来就运行go test,看是否测试通过
在这里插入图片描述
显然,这时候是无法测试通过的

2. 编写可以通过测试的函数

package iteration

// Repeat is a function
func Repeat(character string) string {
	var repeated string
	for i := 0; i < 5; i++ {
		repeated = repeated + character
	}
	return repeated

}

此时测试结果为
在这里插入图片描述

3. 重构

此时重构并引入另一个构造(construct)+= 赋值运算符

package iteration

// Repeat is a function
func Repeat(character string) string {
	var repeated string
	for i := 0; i < 5; i++ {
		repeated += character //重构 +=
	}
	return repeated

}

4. 基准测试

在 Go 中编写基准测试(benchmarks)是该语言的另一个一级特性,它与编写测试非常相似。

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

testing.B 可使你访问隐性命名(cryptically named)b.N。

基准测试运行时,代码会运行 b.N 次,并测量需要多长时间。
代码运行的次数不会对你产生影响,测试框架会选择一个它所认为的最佳值,以便让你获得更合理的结果。

go test -bench=. 来运行基准测试。 (如果在 Windows Powershell 环境下使用 go test -bench=".")

基准测试结果如下所示:
在这里插入图片描述

完成参考教程“迭代”章节的练习

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

首先修改测试文件

package iteration

import "testing"

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

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

此时结果为
在这里插入图片描述
显然,此时函数签名不匹配,接下来就修改函数,让测试可以通过

修改repeat函数

package iteration

// Repeat is a function
func Repeat(character string, number int) string {
	var repeated string
	for i := 0; i < number; i++ {
		repeated += character
	}
	return repeated

}

修改之后再次测试结果为
在这里插入图片描述

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

在测试文件中加入一个示例测试函数ExampleRepeat

package iteration

import (
	"fmt"
	"testing"
)

func ExampleRepeat() {
	var temp string
	temp = Repeat("r", 8)
	fmt.Println(temp)
	//output rrrrrrrr
}

3. 看一下 strings 包。找到你认为可能有用的函数,并对它们编写一些测试。

查看strings包,发现有以下常见的函数
strings包函数
这里我选择Contains、Count、Split、ToLower几个函数来编写测试

package string

import (
	"strings"
	"testing"
)

func TestContains(t *testing.T) {
	s := "0123456"
	substr := "123"
	result := strings.Contains(s, substr)
	expected := true

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

func TestCount(t *testing.T) {
	s := "cheese"
	element := "e"
	result := strings.Count(s, element)
	expected := 3

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

func TestSplit(t *testing.T) {
	s := "a,b,c,d"
	element := ","
	result := strings.Split(s, element)
	expected := [4]string{"a", "b", "c", "d"}

	var flag bool
	flag = true
	for i := 0; i < 4; i++ {
		if result[i] != expected[i] {
			flag = false
		}
	}

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

func TestToLower(t *testing.T) {
	s := "AbCdeF"
	result := strings.ToLower(s)
	expected := "abcdef"

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

测试结果如下:
strings包测试结果

TDD实践(冒泡)

1. 先写测试

package sort

import (
	"fmt"
	"testing"
)

func ExampleBubbleSort() {
	number := [10]int{9, 8, 6, 3, 4, 5, 7, 2, 0, 1}
	result := BubbleSort(number)
	fmt.Println(result)
	//output [0,1,2,3,4,5,6,7,8,9]
}

func TestBubbleSort(t *testing.T) {
	number := [10]int{9, 8, 6, 3, 4, 5, 7, 2, 0, 1}
	result := BubbleSort(number)
	expected := [10]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

	for i := 0; i < 10; i++ {
		if result[i] != expected[i] {
			t.Errorf("expected '%v' but got '%v'", expected, result)//go可以直接输出数组
		}
	}
}

尝试运行测试,发现运行失败(这是显然的,因为我们都还没有写BubbleSort函数)
在这里插入图片描述

2. 编写函数,先让测试运行

package sort

//BubbleSort is a function using for sorting
func BubbleSort(num [10]int) [10]int {
	return num
}

现在发现测试可以运行,但是不能通过(就这样输出原数组当然不可能通过)
在这里插入图片描述

3. 改写BubbleSort函数,使测试通过

package sort

//BubbleSort is a function use for sorting
func BubbleSort(num [10]int) [10]int {
	for i := 0; i < 10; i++ {
		for j := i; j < 10; j++ {
			if num[i] > num[j] {
				temp := num[i]
				num[i] = num[j]
				num[j] = temp
			}
		}
	}
	return num
}

此时测试通过,结果为:
在这里插入图片描述

4. 基准测试

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

基准测试结果为:
在这里插入图片描述
至此,冒泡排序的TDD实现就完成了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值