如何写出好的测试

编程

我们知道编写测试能够带来很多好处。那么除了只是停留在编写测试上,我们应该如何编写好的测试呢?

这里翻译了一篇2012年Eric Lewis的一篇文章《How to write good tests》。

提交历史显示,这篇内容还在一直维护。

##正文开始

01 保持测试代码的短小可读

要实现这一点就必须产品代码进行重构。否则测试端就会因遗留代码而变得腐败。如果测试代码不能很容易的进行重构,那么产品代码同样不容易重构,从而导致了遗留代码。永远都要勇敢的进行重构。

02 避免编写重复的代码

下面这个场景:

一个将参数放置到模版中的方法,代码如下:

public void format(String dateString) {

return String.formate("Update date is %s", dateString);

}

我们对这个测试的代码不应该是这样

[@Test](https://my.oschina.net/azibug)

void should_format_date_label_when_format_given_a_date_string() {

String dateString = "2019/12/20";

String formatedDate = DateUtils.format(dateString);

assertThat(formatedDate).isEquals(String.formate("Update date is %s", dateString))

}

一般而言,不应该在测试和代码之间重复逻辑。因此,上面测试断言中,将业务代码中的实现复制到测试代码中并不可取。在这种情况下,我们应该关注输入/输出,应该使用一个固定期望的结果。

[@Test](https://my.oschina.net/azibug)

void should_format_date_label_when_format_given_a_date_string() {

String dateString = "2019/12/20";

String formatedDate = DateUtils.format(dateString);

assertThat(formatedDate).isEquals("Update date is 2019/12/20");

}

ps:当然既然String.formate()方法能够提供实现,没有必要在封装一个方法,所以上面的例子不是一个好例子,但是意图在说明应该如何验证结果。

03 除了覆盖正向测试,测试用例应该尽可能多的错误代码的路径

通常,这也是练习TDD最好的实现方式。使用TDD可以在设计的时候辨别出造成破坏的地方。不要认为为一个小的代码片段编写简单的测试不值得,你永远不知道什么时候、因为什么而修改这段代码。

可与使用PIT(突变检测系统 http://pitest.org/)来对测试代码的有效性进行检测。

04 不要Mock一个你不拥有的类型

TDD既涉及到测试,也涉及到设计。这不是一个硬性要求,但是如果真的这样做了,很可能会带来一些影响。

场景:假设你在使用一个第三方提供的工具API时。如果对API进行了mock,那么会有什么杨的结果?

  1. 你的测试当时是通过的。
  2. 如果第三方API进行了升级,会有什么结果?会造成单元测试通过,但是实际调用的时候却失败或者并没有返回自己想要的结果。
  3. 这样的设计也表明和第三方API的紧密度不够。
  4. 如果第三方API非常复杂,也会导致当前测试代码必须在大量mock之后才能正常工作。这本身也损害了短小易读的目的。

取而代之,我们应该也是到使用底层这些API的风险,我们应该为第三方库和API编写封装器。为了验证第三方提供API的可用性,我们需要编写集成测试,并让这些测试保持短小、易读。

还有一些人记录了当mock一个不是自己代码库的类型的时候,遇到的痛:

  1. http://davesquared.net/2011/04/dont-mock-types-you-dont-own.html
  2. http://www.markhneedham.com/blog/2009/12/13/tdd-only-mock-types-you-own
  3. http://blog.8thlight.com/eric-smith/2011/10/27/thats-not-yours.html
  4. http://stackoverflow.com/questions/1906344/should-you-only-mock-types-you-own

05 反模式:Mock一切对象

如果所有的代码都mock了,那么我们怎么测试业务代码?不要害怕不使用Mock的方法。

06 不要Mock值对象

为什么有的人会Mock只值对象呢?

因为实例化对方是一件很痛苦的事情。

如果创建一个对象很复杂,那么很可能意味着我们需要进行认真的重构。不Mock的话应该怎么处理?可以使用一些IDE插件、Lombok等,让构造值对象变的简单,也可以在测试类中创建有意义的工厂方法。

abstract class CustomerCreations {

public static Customer customer_with_a_single_item_in_the_basket() {

// long init sequence

}

}

Mockito更加关注对象之间的交互。

07 读读书籍,做做刻意练习

原文中推荐阅读这本书:"Growing Object Oriented Software Guided by Tests"。

但是这本书现在市场已经无法找到了,留在我么身边的还有Code Dojo或者一些其他TDD实践练习,通过反复练习一些场景,思考分析,能够帮助我们写出好的测试。

原文

How to write good tests--Eric Lewis edited this page on Mar 22 · 11 revisions

以上是 如何写出好的测试 的全部内容, 来源链接: utcz.com/z/511949.html

回到顶部