服务计算——迭代与TDD

教程学习

先写测试

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_test.go

尝试运行测试

./repeat_test.go:6:14: undefined: Repeat

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

package iteration

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

结果

repeat_test.go:10: expected 'aaaaa' but got ''

代码补充完整,让它能通过测试

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

与其它语言如 C,Java 或 JavaScript 不同,在 Go 中 for 语句前导条件部分并没有圆括号,而且大括号 { } 是必须的。
我们目前都是使用 := 来声明和初始化变量。然后 := 只是两个步骤的简写。这里我们使用显式的版本来声明一个 string 类型的变量。我们还可以使用 var 来声明函数。

重构

现在是时候重构并引入另一个构造(construct)+= 赋值运算符。

const repeatCount = 5

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

+=是自增赋值运算符(Add AND assignment operator),它把运算符右边的值加到左边并重新赋值给左边。它在其它类型也可以使用,比如整数类型。

基准测试

在 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=".")

练习

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

修改测试代码如下:

package iteration

import “testing”
import “os”
import “strconv”

func TestRepeat(t *testing.T){
	repeated := Repeat(“a”)
	var expected string
	var b int
	s, err := strconv.ParseInt(os.Args[len(os.Args)-1],10,32)
	if err != nil{
		panic(err)
		}
	b = int(s)
	for i := 0;i < b;i++{
		expected += “a”
		}
	if repeated != expected{
		t.Errorf(“expected ‘%q’ but got ‘%q’”,expected,repeated)
		}
	}

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

ExampleRepeat:
func ExampleRepeat(){
	s := Repeat(“a”)
	fit.Println(s)
	}
查看函数文档
安装godoc:
go env -w GO111MODULE=on
go env -w GOPROXY=“https://goproxy.io,direct”
go get golang.org/x/tools/cmd/godoc

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

TDD

基本概念

TDD是测试驱动开发(Test-Driven Development)的英文简称,是敏捷开发中的一项核心实践和技术,也是一种设计方法论。

原理

TDD的原理是在开发功能代码之前,先编写单元测试用例代码,测试代码确定需要编写什么产品代码。

基本思路

TDD的基本思路就是通过测试来推动整个开发的进行,但测试驱动开发并不只是单纯的测试工作,而是把需求分析,设计,质量控制量化的过程。

基本原则

独立测试:不同代码的测试应该相互独立,一个类对应一个测试类(对于C代码或C++全局函数,则一个文件对应一个测试文件),一个函数对应一个测试函数。用例也应各自独立,每个用例不能使用其他用例的结果数据,结果也不能依赖于用例执行顺序。 一个角色:开发过程包含多种工作,如:编写测试代码、编写产品代码、代码重构等。做不同的工作时,应专注于当前的角色,不要过多考虑其他方面的细节。
测试列表:代码的功能点可能很多,并且需求可能是陆续出现的,任何阶段想添加功能时,应把相关功能点加到测试列表中,然后才能继续手头工作,避免疏漏。
测试驱动:即利用测试来驱动开发,是TDD的核心。要实现某个功能,要编写某个类或某个函数,应首先编写测试代码,明确这个类、这个函数如何使用,如何测试,然后在对其进行设计、编码。
先写断言:编写测试代码时,应该首先编写判断代码功能的断言语句,然后编写必要的辅助语句。
可测试性:产品代码设计、开发时的应尽可能提高可测试性。每个代码单元的功能应该比较单纯,“各家自扫门前雪”,每个类、每个函数应该只做它该做的事,不要弄成大杂烩。尤其是增加新功能时,不要为了图一时之便,随便在原有代码中添加功能,对于C++编程,应多考虑使用子类、继承、重载等OO方法。
及时重构:对结构不合理,重复等“味道”不好的代码,在测试通过后,应及时进行重构。
小步前进:软件开发是复杂性非常高的工作,小步前进是降低复杂性的好办法。

优缺点

优点:在任意一个开发节点都可以拿出一个可以使用,含少量bug并具一定功能和能够发布的产品。
缺点:增加代码量。测试代码是系统代码的两倍或更多,但是同时节省了调试程序及挑错时间。

使用TDD思想实现快排

先写测试

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

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

写一个简单的Quicksort函数,但此时的数组并没有排序,仍然按照原顺序输出

package quicksort

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

代码补充完整,让它能通过测试

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

基准测试

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值