1.保持单元测试小巧、快速

理论上,任何代码提交前都应该完整跑一遍全部测试套件。保持测试代码执行符合预期,这样可以缩短迭代开发周期。程序员

2.单元测试应该是全自动/非交互式的

测试套件一般是按期执行的,执行过程必须彻底自动化才有意义。输出结果须要人工检查的测试不是一个好的单元测试。面试

3.让单元测试很容易跑起来

对开发环境进行配置,最好是敲一条命令或是点击一个按钮就能把单个测试用例或测试套件跑起来。数据库

4.对测试进行评估

对执行的测试进行覆盖率分析,获得精确的代码执行覆盖率,并调查哪些代码未被执行。app

5.当即修正失败的测试

每一个开发人员在提交前都应该保证新的测试用例执行成功,当有代码提交时,现有测试用例也都能跑通。

若是一个按期执行的测试用例执行失败,整个团队应该放下手上的工做先解决这个问题。框架

6.把测试维持在单元级别

单元测试即类(Class)的测试。一个“测试类”应该只对应于一个“被测类”,而且“被测类”的行为应该被隔离测试。必须谨慎避免使用单元测试框架来测试整个程序的工做流,这样的测试即低效又难维护。工做流测试(译注:指跨模块、类的数据流测试)有它本身的地盘,但它毫不是单元测试,必须单独创建和执行。dom

7.由简入繁

再简单的测试也远远赛过彻底没有测试。一个简单的“测试类”会促使创建“被测类”基本的测试骨架,能够对构建环境、单元测试环境、执行环境以及覆盖率分析工具等有效性进行检查,同时也能够证实“被测类”可以被整合和调用。

下面即是单元测试版的“Hello, world!”:函数

void testDefaultConstruction()

{

Foo foo = new Foo();

assertNotNull(foo);

}

8.保持测试的独立性

为了保证测试稳定可靠且便于维护,测试用例之间决不能有相互依赖,也不能依赖执行的前后次序。(实际上TestNG有提供依赖的功能,或许某些场景也须要依赖。)工具

9.Keep tests close to the class being tested

[译注:有意翻译该规则,我的认为本条规则值得商榷,大部分C++、Objective-C和Python库均把测试代码从功能代码目录中独立出来,一般是建立一个和src目录同级的tests目录,被测模块、类名以前也经常不加Test 前缀。这么作保证功能代码和测试代码隔离、目录结构清晰,而且发布源码的时候更容易排除测试用例单元测试

]

If the class to test is Foo the test class should be called FooTest (not TestFoo) and kept in the same package (directory) as Foo. Keeping test classes in separate directory trees makes them harder to access and maintain.

Make sure the build environment is configured so that the test classes doesn’t make its way into production libraries or executables.

10.合理的命名测试用例

确保每一个方法只测试“被测类”的一个明确特性,并相应的命名测试方法。典型的命名俗定是“test[MethodName]”,好比“testSaveAs()”、“testAddListener()”、“testDeleteProperty()”等。测试

11.只测公有接口

单元测试能够被定义为经过类的公有API对类进行测试。一些测试工具容许测试一个类的私有成员,但这种作法应该避免,它让测试变得繁琐并且更难维护。若是有私有成员确实须要进行直接测试,能够考虑把它重构到工具类的公有方法中。但要注意这么作是为了改善设计,而不是帮助测试。

12.当作是黑盒

站在第三方使用者的角度,测试一个类是否知足规定的需求。并设法让它出问题。

13.当作是白盒

毕竟被测试类是程序员自写自测的,应该在最复杂的逻辑部分多花些精力测试。

14.芝麻函数也要测试

一般建议全部重要的函数都应该被测试到,一些芝麻方法好比简单的setter和getter均可以忽略。可是仍然有充分的理由支持测试芝麻函数:

“芝麻”很难定义,对于不一样的人有不一样的理解。

从黑盒测试的观点看,是没法知道哪些代码是芝麻级别的。

即使是再芝麻的函数,也可能包含错误,一般是“复制粘贴”代码的后果:

private double weight_;

private double x_, y_;

public void setWeight(int weight)

{

weight = weight_; // error

}

public double getX()

{

return x_;

}

public double getY()

{

return x_; // error

}

所以建议测试全部方法,毕竟芝麻用例也容易测试。

15.先关注执行覆盖率

区别对待“执行覆盖率”和“实际测试覆盖率”。测试的最初目标应该是确保较高的执行覆盖率,这样能保证代码在 少许参数值输入时能执行成功。一旦执行覆盖率就绪,就应该开始改进测试覆盖率了。注意,实际的测试覆盖率很难衡量(并且每每趋近于0%)。

思考如下公有方法:

void setLength(double length);

调用“setLength(1.0)”你可能会获得100%的执行覆盖率。但要达到100%的实际测试覆盖率,有多少个 double浮点数这个方法就必须被调用多少次,而且要一一验证行为的正确性。这无疑是不可能的任务。

16.覆盖边界值

确保参数边界值均被覆盖。对于数字,测试负数、0、正数、最小值、最大值、NaN(非数字)、无穷大等;对于字符串,测试空字符串、单字符、非ASCII字符串、多字节字符串等;对于集合类型,测试空、一、第一个、最后一个等;对于日期,测试1月1号、2月29号、12月31号等。被测试的类自己也会暗示一些特定状况下的边界值。 要点是尽量完全的测试这些边界值,由于它们都是主要“疑犯”。

17.提供一个随机值生成器

当边界值都覆盖了,另外一个能进一步改善测试覆盖率的简单方法就是生成随机参数,这样每次执行测试都会有不一样的输入。

想要作到这点,须要提供一个用来生成基本类型(如:浮点数、整型、字符串、日期等)随机值的工具类。生成器应该覆盖各类类型的全部取值范围。

若是测试时间比较短,能够考虑再裹上一层循环,覆盖尽量多的输入组合。下面的例子是验证两次转换“little endian”和“big endian”字节序后是否返回原值。因为测试过程很快,可让它跑上个一百万次。

void testByteSwapper()

{

for (int i = 0; i < 1000000; i++) {

double v0 = Random.getDouble();

double v1 = ByteSwapper.swap(v0);

double v2 = ByteSwapper.swap(v1);

assertEquals(v0, v2);

}

}

18.每一个特性只测一次

在测试模式下,有时会不由自主的滥用断言。这种作法会致使维护更困难,须要极力避免。仅对测试方法名指示的特性进行明确测试。

由于对于通常性代码而言,保证测试代码尽量少是一个重要目标。

19.使用显式断言

应该老是优先使用“assertEquals(a, b)”而不是“assertTrue(a == b)”,由于前者会给出更有意义的测试失败信息。在事先不肯定输入值的状况下,这条规则尤其重要,好比以前使用随机参数值组合的例子。

20.提供反向测试

反向测试是指刻意编写问题代码,来验证鲁棒性和可否正确的处理错误。

假设以下方法的参数若是传进去的是负数,会立马抛出异常:

void setLength(double length) throws IllegalArgumentException

能够用下面的方法来测试这个特例是否被正确处理:

try {

setLength(-1.0);

fail(); // If we get here, something went wrong

}

catch (IllegalArgumentException exception) {

// If we get here, all is fine

}

21.代码设计时谨记

编写和维护单元测试的代价是很高的,减小代码中的公有接口和循环复杂度是下降成本和使高覆盖率测试代码更易于编写和维护的有效方法。

一些建议:

22.使类成员常量化,在构造函数中进行初始化。减小setter方法的数量。

23.限制过分使用继承和公有虚函数。

24.经过使用友元类(C++)或包做用域(Java)来减小公有接口。

25.避免没必要要的逻辑分支。

26.在逻辑分支中编写尽量少的代码。

27.在公有和私有接口中尽可能多用异常和断言验证参数参数的有效性。

28.限制使用快捷函数。

对于黑箱而言,全部方法都必须一视同仁的进行测试。考虑如下简短的例子:

public void scale(double x0, double y0, double scaleFactor)

{

// scaling logic

}

public void scale(double x0, double y0)

{

scale(x0, y0, 1.0);

}

29.删除后者能够简化测试,但用户代码的工做量也将略微增长。

30.不要访问预设的外部资源

单元测试代码不该该假定外部的执行环境,以便在任什么时候候和任何地方都能执行。为了向测试提供必需的资源,这些资源应该由测试自己提供。

好比:一个解析某类型文件的类,能够把文件内容嵌入到测试代码里。在测试的时候写入到临时文件,测试结束再删除,而不是从预约的地址直接读取。

31.权衡测试成本

不写单元测试的代价很高,可是写单元测试的代价一样很高。要在这二者之间作适当的权衡,若是用执行覆盖率来衡量,业界标准一般在80%左右。

很典型的,读写外部资源的错误处理和异常处理就很难达到百分百的执行覆盖率。模拟数据库在事务处理到一半时发生故障并非办不到,但相对于进行大范围的代码审查,代价可能太大了。

32.安排测试优先次序

单元测试是典型的自底向上过程,若是没有足够的资源测试一个系统的全部模块,就应该先把重点放在较底层的模块。

33.测试代码要考虑错误处理

考虑下面的这个例子:

Handle handle = manager.getHandle();

assertNotNull(handle);

String handleName = handle.getName();

assertEquals(handleName, "handle-01");

若是第一个断言失败,后续语句会致使代码崩溃,剩下的测试都没法执行。任什么时候候都要为测试失败作好准备,避免单个失败的测试项中断整个测试套件的执行。上面的例子能够重写成:

Handle handle = manager.getHandle();

assertNotNull(handle);

if (handle == null) return;

String handleName = handle.getName();

assertEquals(handleName, "handle-01");

34.写测试用例重现Bug

每上报一个Bug,都要写一个测试用例来重现这个Bug(即没法经过测试),并用它做为成功修正代码的检验标准。

35.了解局限

单元测试永远没法证实代码的正确性!!

一个跑失败的测试可能代表代码有错误,但一个跑成功的测试什么也证实不了。

单元测试最有效的使用场合是在一个较低的层级验证并文档化需求,以及回归测试:开发或重构代码,不会破坏已有功能的正确性。

以上内容就是本篇的所有内容以上内容但愿对你有帮助,有被帮助到的朋友欢迎点赞,评论。

若是对软件测试、接口测试、自动化测试、面试经验交流。感兴趣能够关注我,咱们会有同行一块儿技术交流哦。

芝麻翻译软件测试,细数35个单元测试准则 “Hello, world!”相关推荐

  1. 细数二十世纪最伟大的10大算法

    导读:作者July总结了一篇关于计算方法的文章< 细数二十世纪最伟大的10大算法 >. 一.1946 蒙特卡洛方法 [1946: John von Neumann, Stan Ulam, ...

  2. 细数近年来机器学习研究的几大怪现状

    人工智能领域的发展离不开学者们的贡献,然而随着研究的进步,越来越多的论文出现了「标题党」.「占坑」.「注水」等现象,暴增的顶会论文接收数量似乎并没有带来更多技术突破.最近,来自卡耐基梅隆大学的助理教授 ...

  3. hua图软件 mac_细数Mac上那些好用且免费的软件(四)

    许多朋友购买了Mac电脑之后发现很多软件都没有,而且苹果商店好多软件都是收费的.那有没有免费的软件也能满足日常的需求呢?macw小编就为大家推荐一些免费且超级好用的软件,赶快来看看有没有你需要的吧! ...

  4. 百密一疏,防不胜防,细数那些大型数据库建设过程中绕不开的坑

    构建大型数据库时,无论最开始的设计多么精妙,到后续操作的时候或多或少都会遇到一些问题,本文将来细数大型数据库中不可避免会遇到的问题. 原文标题:Feature Casualties of Large ...

  5. 9月操盘策略 热点一一细数(2)

    9月操盘策略 热点一一细数(2) 天辰证券 29家公司8月上会创近三年新高 新股发行来势凶猛 在创业板企业陆续拿到反馈函的当期,主板的发行审核也悄然提速. "6月底报进会里的中小板项目,8月 ...

  6. 细数百度公司的知名开源项目

    [企业开源]细数百度公司的知名开源项目 关于百度开源的更多信息请参看以下网址: 百度开源平台: http://oss.baidu.com/ 百度EFX团队Github主页: https://githu ...

  7. 通天塔导游 - 细数各种编程语言优缺点

    通天塔导游 - 细数各种编程语言优缺点 (译注:圣经记载:在远古的时候,人类都使用一种语言,全世界的人决定一起造一座通天的塔,就是巴别塔,后来被上帝知道了,上帝就让人们使用不同的 语言,这个塔就没能造 ...

  8. 《八股文》细数Java线程、并发、锁,温故而知新

    <八股文>细数Java线程.并发.锁,温故而知新 基础 1. 并行.并发有什么区别? 2. 说说什么是进程和线程? 3. 说说线程有几种创建方式? 4. 为什么调用start()方法时会执 ...

  9. 细数T-BOX中TI的明星产品之 线性稳压器 | 第五节TPS7B7701-Q1:为车载应用保驾护航

    汽车新热点:细数T-BOX中TI的明星产品(进行中) Interface PHY 第一节     DP83TC811S-Q1:车载以太网让您的T-BOX如虎添翼 CAN 第二节   TCAN1042- ...

最新文章

  1. FPGA的历史、现状和未来
  2. 概率论与数理统计专业术语
  3. 编程之美-数组分割方法整理
  4. usb打印机命令_打印机脱机怎么办 打印机脱机解决方法【详解】
  5. python序列5位置_Python序列构成的数组
  6. 热门剧本杀与 SaaS 的不解之缘
  7. Eclipse上GIT插件EGIT使用手册之五_查看历史记录
  8. jzoj4739-[雅礼联考GDOI2017模拟9.2]Ztxz16学图论【LCT,树状数组】
  9. POJ-1191 棋盘分割 动态规划
  10. 802.11 monitor模式
  11. 计算机网络 五层网络协议各司其职,一次讲清楚
  12. 《机器学习系统设计:Python语言实现》一2.1 Python与机器学习
  13. 郑义宣就任韩国现代汽车集团会长;爱立信携手中国电信运用爱立信频谱共享技术 | 美通企业日报...
  14. 解密深圳IT人士的当前薪情【转自:中国it实验室】
  15. 冒泡排序 java代码实现
  16. Keil5使用AC6编译器
  17. 手札-11(京东实战手札)
  18. App Store上推广App的实战经验
  19. 非常全面的支付宝钱包系统架构图解
  20. 20步打造完美网站布局设计

热门文章

  1. IO流(IO异常处理方式)
  2. nvm 装 nodejs 重启终端失效的解决方法
  3. get/post时中文乱码问题的解决办法
  4. [问题解决]不使用PWM调速系统,彻底解决一个L298N带动两个电机却转速不同的问题
  5. Xcode 9“ iPhone忙:准备对iPhone的调试器支持”
  6. 如何避免在Excel VBA中使用选择
  7. Node.js + Nginx-现在怎么办?
  8. 在Go中构建区块链 第7部分:网络
  9. playbook 实例
  10. gj11 多线程、多进程和线程池编程