通过测试学习go语言之迭代

通过测试学习go语言之迭代

一、 完成迭代章节的练习

写一个重复字符五次的函数编写测试。

1、 先写测试

在src文件夹中创建一个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函数未定义。
error

2、编写Repeat函数

既然Repeat函数未定义,我们便先定义一个Repeat函数,使得测试代码能够跑起来。
在iteration文件夹下添加新的.go文件,命名为repeat.go,代码如下:

package iteration

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

此时运行go test,会输出expected ‘“aaaaa”’ but got ‘""’,说明我们写的Repeat函数能够成功运行。
fail
接着我们要想办法让Repeat函数能够成功通过测试,观察测试文件可知,只需要把输入的字符重复5遍即可,所以我们可以使用for语句来完成测试。

package iteration

func Repeat(character string) string{
	var repeated string
	for i:=0 ; i<5 ; i++{
		repeated += character
	}

	return repeated
}

运行go test,便可以发现测试成功通过了。
pass
最后我们尝试编写一个基准测试,具体代码如下:

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

运行 go test -bench=.来测试代码运行时间,结果如下:
在这里插入图片描述
可以看到代码共运行了一千万次,平均每次运行时间为145ns

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

要指定字符重复的次数,只需要在Repeat函数中加上一个参数,传入重复次数即可。
修改后的repeat_test.go代码如下:

package iteration

import  "testing"

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

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

接着修改repeat.go中的Repeat函数,使它可以传入两个参数(一个string类型,一个int类型):

package iteration

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

	return repeated
}

运行go test,会发现代码可以成功跑起来,但是测试出错了,这是因为我设置的重复次数是6,但是结果里面的字符串只有5个a。
fail2
将重复次数修改为5,便能通过测试了。
在这里插入图片描述

3-2、写一个 ExampleRepeat 来完善你的函数文档

从之前的整数章节中我们可以发现,ExampleRepeat函数是存在与repeat_test.go文件中的。所以我们需要在repeat_test.go文件中新增一个ExampleRepeat函数,同时注意因为这里我们要输出数据,所以要import “fmt”
在这里插入图片描述

func ExampleRepeat()  {
	repeated := Repeat("a", 6)
	fmt.Println(repeated)
	//Output: aaaaa
}

在这里插入图片描述

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

建立一个stringTest文件夹,然后下面相关的strings包的测试内容代码都放在此文件夹中。

(1)查找操作(Contains())

判断给定字符串s中是否包含子串substr, 找到返回true, 找不到返回false,特殊情况下,若字串是空串也返回true。
contains_test.go:

package stringTest

import (
		"testing"
		"strings"
)

func TestContains(t *testing.T){
	contains := strings.Contains("children", "child")
	expected := true

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

这里在错误信息输出处我一开始用的%q,但是报错了,说bool类型的变量不能用%q,所以我改成了%v,用来表示相应类型的默认格式。
在这里插入图片描述
最终的输出结果为:
在这里插入图片描述

(2)统计操作(Count())

统计字串在原字符串中的出现次数,当字串为空时,返回值为字符串长度+1。
count_test.go:

package stringTest

import(
	"testing"
	"strings"
)

func TestCount(t *testing.T){
	count  := strings.Count("hello,world!", "o")
	expected := 2

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

最终的输出结果为:
在这里插入图片描述
测试成功。

(3)替换操作(Replace())

用新字符串去替换旧的字符串,共替换次数为n次,最后返回替换后的字符串。特殊的,若n<0会替换掉所有的旧的字符串。
replace_test.go:

package stringTest

import (
	"testing"
	"strings"
)

func TestReplace(t *testing.T){
	ans := strings.Replace("hi hi hi", "i", "ey", 2)
	expected := "hey hey hey"
	
	if ans != expected{
		t.Errorf("expected %q but got %q", expected, ans)
	}
}

最终输出结果为:
在这里插入图片描述
测试成功。

二、概念理解

1、TDD

全称为测试驱动开发(Test-Driven Development),其原理是在开发功能代码之前,先编写单元测试用例代码,测试代码确定需要编写什么产品代码。
TDD的基本思路是通过测试来推动整个开发的进行,但是这里的测试驱动开发并不只是单纯的测试工作,而是把需求分析、设计、质量控制量化的过程。
TDD周期

2、重构

重构(Refactoring)是通过调整程序代码,来改善软件的质量、性能,使程序的设计模式和架构更趋于合理,提高软件的扩展性和维护性。
重构可以降低项目的耦合度,使项目更加模块化,有利于项目的开发效率和后期的维护,也有利于代码的再利用。

3、测试

测试时使用人工或者自动的手段来运行或测定某个程序代码的过程,目的在于检验程序是否满足需求,以确保程序能够按照预定的方式正确地运行。
为了发现程序中的错误,在设计测试时我们应尽量设计能够暴露错误的测试用例。

4、基准测试

基准测试是指通过设计科学的测试方法、测试工具和测试系统,实现对一类测试对象的某项性能指标进行定量的和可对比的测试。
基准测试的关键是要获得一致的、可再现的结果,这样可以减少重新运行测试的次数,使得测试的产品和产品产生的数据更加可信。
基准测试的步骤:观察→假设→预测→环境控制→测试→推论和结论

三、程序设计

选择一个算法如“快排”,模仿教程内容结构,写一个Go语言某算法实现TDD的实践报告

1、算法介绍

快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序。它采用了一种分治的策略,通常称其为分治法(Divide-and-ConquerMethod)。
该方法的基本思想是:
1.先从数列中取出一个数作为基准数。
2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。
3.再对左右区间重复第二步,直到各区间只有一个数。

2、代码实现

(1)先写测试文件quicksort_test.go

package quicksort

import "testing"

var arr = [] int  {1, 3, 5, 8, 9, 4, 2, 7, 10, 6, 12, 11}
var maxn int = 12

func TestQuicksort(t *testing.T){
	Quicksort(arr, 0, 11)
	expected := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}

	flag := true
	for i:=0 ; i<12 ; i++{
		if arr[i] != expected[i]{
			flag = false
		}
	}

	if flag == false{
		t.Errorf("Expected %v but got %v", expected, arr)
	}
}

(2)然后编写一个简单的quicksort函数使得测试文件能够跑起来。

package quicksort

func Quicksort(arr []int, start int, end int){
	return 
}

此时运行go test可以得到如下结果:
fail
这时的arr数组并没有进行排序,还是按照原顺序输出。
(3)代码补全,完善quicksort函数。

package quicksort

func Quicksort(arr []int, start int, end int){
	if start >= end{
		return
	}

	num := arr[(start+end)/2]
	i := start
	j := end

	for arr[j] > num{
		j--
	}
	for arr[i] < num{
		i++
	}

	temp := arr[i]
	arr[i] = arr[j]
	arr[j] = temp

	i++
	j--

	if i < end{
		Quicksort(arr, i, end)
	}
	if j > start{
		Quicksort(arr, start, j)
	}
}

运行go test -v,得到结果如下:
在这里插入图片描述
成功通过测试。
(4)基准测试
在测试文件中添加基准测试函数BenchmarkQuicksort(),使测试代码运行b.N次,并测试运行时间。

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

运行go test -bench=.命令,测试代码运行的时间,结果如下:
在这里插入图片描述
发现运行一次代码要102ns,为了测试这个结果运行了20000000次(两千万次)。

四、gitee地址

代码传送门

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值