摘要:TDD(Test Driven Development),测试驱动开发。期望局部最优到全局最优,这个是一种非常不错的好习惯。

了解Golang的测试之前,我们先了解一下go语言自带的测试工具。

go test工具

Go语言中的测试依赖go test命令。编写测试代码和编写普通的Go代码过程是类似的,并不需要学习新的语法、规则或工具。

go test命令是一个按照一定约定和组织的测试代码的驱动程序。在包目录内,所有以_test.go为后缀名的源代码文件都是go test测试的一部分,不会被go build编译到最终的可执行文件中。

在*_test.go文件中有三种类型的函数,单元测试函数、基准测试函数和示例函数。

运行流程

go test命令会遍历所有的*_test.go文件中符合上述命名规则的函数,然后生成一个临时的main包用于调用相应的测试函数,然后构建并运行、报告测试结果,最后清理测试中生成的临时文件。

单元测试

以下是来自wiki对于单元测试的定义

在计算机编程中,单元测试(英语:Unit Testing)又称为模块测试,是针对程序模块(软件设计的最小单位)来进行正确性检验的测试工作。程序单元是应用的最小可测试部件。在过程化编程中,一个单元就是单个程序、函数、过程等;对于面向对象编程,最小单元就是方法,包括基类(超类)、抽象类、或者派生类(子类)中的方法。

通常来说,程序员每修改一次程序就会进行最少一次单元测试,在编写程序的过程中前后很可能要进行多次单元测试,以证实程序达到软件规格书要求的工作目标,没有程序错误;虽然单元测试不是必须的,但也不坏,这牵涉到项目管理的政策决定。

每个理想的测试案例独立于其它案例;为测试时隔离模块,经常使用stubs、mock[1]或fake等测试马甲程序。单元测试通常由软件开发人员编写,用于确保他们所写的代码符合软件需求和遵循开发目标。它的实施方式可以是非常手动的(透过纸笔),或者是做成构建自动化的一部分。

简单来说,单元测试就是程序员自己对于自己的代码进行测试,而一个单元就是单个程序、函数、过程等;对于面向对象编程,最小单元就是方法,包括基类(超类)、抽象类、或者派生类(子类)中的方法。

更有一种开发手法,那就是TDD(Test Driven Development),测试驱动开发。期望局部最优到全局最优,这个是一种非常不错的好习惯。

请注意这里的局部最优的,局部,并不是函数内的详细。而是整个函数。甚至是一个类,等等。

因为有些函数内部的最优,并非这个函数的最优。这点我们需要格外的注意。若有兴趣,可了解一下有点关系的贪心算法。

测试函数格式

其中参数t用于报告测试失败和附加的日志信息。

testing.T的拥有的方法如下:

说了这么多,那么我们来实现一个简单的string中的Split函数,并对他进行单元测试,然后我们在剖析代码。了解单元测试的相关规范。

运行结果如下

说明测试成功,本次通过。当然你也可以在Terminal里面直接运行go test,命令,如下所示

温馨提示:关于可能造成运行test不成功原因

直接在split_test.go,运行。

我们或许知道,go是以文件夹的方法来区分项目。所以当前文件,并不能跑到旁边文件中去找到Split,以至于测试失败。或未达到预期效果。

那么正确的打开方式应该是?

在goland中,鼠标右键点击run测试文件所在的文件夹,选择后面第二个 go test projectFileName。

在Terminal中,应在测试文件所在的文件夹的路径中,进行go test [arge...]。

示例看完了,那么我们进行简单的剖析。我们先从函数文件说起,(也就是这里的splits.go)。

1. 不在是package main,而是packge projectFileName

2. 函数名大写,大写意味着公有函数,可支持外部调用

测试文件

1. 文件名为'*_test.go'

2. 不在是package main,而是packge projectFileName

3. 函数名为TestFuncName

基准测试

基准测试函数格式

基准测试就是在一定的工作负载之下检测程序性能的一种方法。基准测试的基本格式如下:

基准测试以Benchmark为前缀,需要一个*testing.B类型的参数b,基准测试必须要执行b.N次,这样的测试才有对照性,b.N的值是系统根据实际情况去调整的,从而保证测试的稳定性。 testing.B拥有的方法如下:

基准测试示例

我们为我们自己写的Split函数编写基准测试如下:

其中BenchmarkSplit:表示对Split函数进行基准测试

BenchmarkSplit-8:数字8表示GOMAXPROCS的值,这个对于并发基准测试很重要

5188407和206ns/op:表示每次调用Split函数耗时203ns

我们还可以为基准测试添加-benchmem参数,来获得内存分配的统计数据。

112 B/op:表示每次操作内存分配了112字节

3 allocs/op:则表示每次操作进行了3次内存分配!!!

优化后代码如下:

优化后代码如下

这个使用make函数提前分配内存的改动,减少了2/3的内存分配次数,并且减少了一半的内存分配。

仅仅小小的一处改动,就引起如此大的性能改变。so good量变产生质变

性能比较函数

上面的基准测试只能得到给定操作的绝对耗时,但是在很多性能问题是发生在两个不同操作之间的相对耗时,比如同一个函数处理1000个元素的耗时与处理1万甚至100万个元素的耗时的差别是多少?再或者对于同一个任务究竟使用哪种算法性能最佳?我们通常需要对两个不同算法的实现使用相同的输入来进行基准比较测试。

性能比较函数通常是一个带有参数的函数,被多个不同的Benchmark函数传入不同的值来调用。举个例子如下:

例如我们编写了一个计算斐波那契数列的函数如下:

我们编写的性能比较函数如下:

运行基准测试:

这里需要注意的是,默认情况下,每个基准测试至少运行1秒。如果在Benchmark函数返回时没有到1秒,则b.N的值会按1,2,5,10,20,50,…增加,并且函数再次运行。

最终的BenchmarkFib40只运行了两次,每次运行的平均值只有不到一秒。像这种情况下我们应该可以使用-benchtime标志增加最小基准时间,以产生更准确的结果。例如:

这一次BenchmarkFib40函数运行了50次,结果就会更准确一些了。

使用性能比较函数做测试的时候一个容易犯的错误就是把b.N作为输入的大小,例如以下两个例子都是错误的示范:

本文分享自华为云社区《Golang代码测试(code review)》,原文作者:PayneWu 。

点击关注,第一时间了解华为云新鲜技术~

Golang代码测试:一点到面用测试驱动开发相关推荐

  1. 优美的测试代码 - 行为驱动开发(BDD)

    可理解的代码非常重要,测试代码也是如此.在我看来,优秀的测试代码,必须做到一个重要的事情就是保持测试逻辑的清晰.一个完整的测试案例通常包括三个部分: 1. SetUp 2. Exercise 3. V ...

  2. 如何编写可测试的golang代码

    每次在开发之前,我都会考虑写好单元测试,但是随着开发的进行,就会发现事情没有这么简单,因为更多时候项目中间夹杂着很多的数据库操作,网络操作,文件操作等等,每次涉及到有这些操作的单元测试,都要花费很大的 ...

  3. 测试你的前端代码 - part3(端到端测试)

    本文作者:Gil Tayar 编译:胡子大哈 翻译原文:http://huziketang.com/blog/posts/detail?postId=58d50da37413fc2e8240855c ...

  4. 存根类 测试代码 java_有关为旧版代码创建存根的更多信息–测试技术7

    存根类 测试代码 java 在我的上一个博客中 ,我谈到了如何处理行为不佳的不可测试的 (1) SitePropertiesManager 类,以及如何通过提取接口来创建存根. 但是,如果由于旧类的源 ...

  5. 有关为旧版代码创建存根的更多信息–测试技术7

    在上一个博客中 ,我谈到了如何处理行为不佳的不可测试的 (1) SitePropertiesManager 类,以及如何通过提取接口来创建存根. 但是,如果由于旧类的源代码已被锁定在第三方JAR文件中 ...

  6. (保守群组测试 非保守群组测试 二次重复测试 自适应二次重复测试)四种群体测试的C++代码

    目录 原理 保守组检测 非保守组检测 二次重复测试 自适应二次重复测试 四种测试方法的核心代码 保守群组测试 非保守群组测试 二次重复测试与自适应二次重复测试 测试代码 参考文献 原理 假设该病在人群 ...

  7. python代码测试 vim_用 Hypothesis 快速测试你的 Python 代码

    点击上方"Python编程时光",选择"加为星标"第一时间关注Python技术干货! 介绍 无论你使用哪种编程语言或框架,测试都非常重要.Hypothesis是 ...

  8. webstorm代码行数统计_来测试下 2019 你一共写了多少行代码?

    写啊写代码,2019 你都写了多少行代码呢 自己动手实现一个代码统计工具 导入所需的库 这个程序需要用到的库有:os,time 这两个库都是 Python 自带的,所以我们直接 import 就行 i ...

  9. python测试代码怎么写_python unittest编写测试代码

    做开发的朋友在写代码的同时一般都会写测试代码,这对于做运维的同学却很少用. 今天我们就来写写测试代码,用unittest模块. cat test.py import unittest def IsOd ...

  10. 【Golang】解决Go test执行单个测试文件提示未定义问题

    [Golang]解决Go test执行单个测试文件提示未定义问题 参考文章: (1)[Golang]解决Go test执行单个测试文件提示未定义问题 (2)https://www.cnblogs.co ...

最新文章

  1. [转]MySQL查询表内重复记录
  2. Spark和Scala当中的collect方法的用法和例子
  3. c100f3网站服务器,0201N100F250LT
  4. python中类中属性和方法的具体定义方法和使用
  5. 基于注释的Spring MVC Web应用程序入门
  6. Android基础教程(四)之------获取手机联系人信息
  7. core dump 简介
  8. android 银行接口,iOS/Android银行卡识别sdk/开发包/api/接口
  9. 使用Android Studio开发/调试Android源码
  10. 大三暑假前端实习日志
  11. MacbookAir2011用U盘重装10.13.6High Sierra系统
  12. 已解决,Nik报错an error occurred while extracting
  13. 激情彭拜的10月英语学习
  14. 将数组分成两部分,使得 |sum1 - sum2| 最小. LeetCode - 1049
  15. 笔记本电脑键盘被锁如何解锁
  16. 隧道二衬钢筋(一键生成)
  17. GotW#63 狂乱的代码
  18. SystemSoftware
  19. 网易2018校园招聘:游历魔法王国 [python]
  20. 算法面试题:扔玻璃杯的学问

热门文章

  1. 【OpenCV入门教程之二】 一览众山小:OpenCV 2.4.8 or OpenCV 2.4.9组件结构全解析
  2. BP神经网络matlab代码
  3. 存储器RAM ROM FLASH介绍
  4. Element Dialog弹框回到顶部
  5. 前端页面读取ukey
  6. linux版本qq的安装
  7. java开发特殊技能怎么填_【程序员简历】IT技能/编程技能应当怎么写?
  8. 调查:2013年十大急需的热门IT技能
  9. C#获取电脑硬件信息(CPU ID、主板ID、硬盘ID、BIOS编号)
  10. Vue3配置路由ERROR in [eslint]报错问题