《JUnit实战(第2版)》—— 1.1 证实它能运行

简介:

本节书摘来异步社区《JUnit实战(第2版)》一书中的第1章,第1.1节,作者:【美】Petar Tahchiev , Felipe Leme , Vincent Massol , Gary Gregory,更多章节内容可以访问云栖社区“异步社区”公众号查看。

1.2 从零开始

JUnit实战(第2版)
为了我们的第一个示例,我们创建一个简单的Calculator类,可以将两个数相加。Calculator类为了客户端提供了一个API,但并没有包含一个用户界面,如代码1.1所示。

代码1.1 用于测试的Calculator类

b71e32457d255327b8cfa35ecc91c5210be01ad8

虽然这里没有列出文档,但Calculator的add(double,double)方法的意图显然是接受两个double值并以double类型返回它们的和。虽然编译器能够告诉我们它通过了编译,但是我们也应该确保它在运行期间能够正常工作。单元测试的核心原则是“任何没有经过自动测试的程序功能都可以当作不存在1”。add方法代表了Calculator的一个核心功能。我们拥有了一些能够实现该功能的代码,现在缺少的只是一个证明实现能够正常工作的自动测试。

add方法如此简单怎么可能出错?

目前add方法的实现非常简单,以致不可能出错。假如add只是一个不重要的工具方法,那么我们可能就不会直接测试它。在这种情况下,如果add出错,那么针对使用add的所有方法的所有测试都将会出错。于是,add方法将被间接测试,虽然如此,但还是算被测试过了。在Calculator程序中,add不只是一个方法,而且是一项程序功能。为了确保程序正确运行,大部分开发人员都会期待一个针对add功能的自动测试,无论实现看起来多么简单。在某些情况下,我们可以通过自动功能测试或自动验收测试来证明程序功能。关于软件测试的一般内容,可以参阅本书的第3章内容。

在这个时候进行任何测试看起来都会有些困难。因为我们甚至都没有用户界面可以输入一对double值。我们可以编写一个命令行小程序,它能够在我们输入两个double值后显示运行结果。这样一来,就同时测试了我们自己输入数字及求和的能力了。这可比我们想要的还要多。我们想要知道的是,这个工作单元是否能够对两个double值求和并且返回正确的值,而并没想测试程序员是否能够输入数字!

与此同时,如果想花大力气测试我们的工作成果,那么也应该尽量使得这一份投入物有所值。在我们编写add(double,double)方法时,知道它能够正常工作这固然很好,但是我们真正想知道的是,在交付应用程序的其他部分后或者在任何时候进行了后续的修改,这个方法是否依然够能正常工作。如果我们把这些需求放在一起考虑,那么我们就会产生一个想法:为add方法编写一个简单的测试。

这个测试程序可以将已知的值传给方法,并判断运行结果是否与我们的预期一致。我们也可以随后再次运行该程序,以确保该方法能够随着应用程序的增长而持续正常工作。我们能够编写的最简单的测试程序是什么样的呢?如代码1.2所示的CalculatorTest程序怎么样呢?

代码1.2 一个简单的CalculatorTest程序

3421e1ad4297a8c8b3a55b2cebd4d0aa93cef27d

第一个CalculatorTest非常简单。它创建了Calculator的一个实例,传递给它两个数字,并且检查运行结果。如果运行结果与我们的预期不一致,那么我们就在标准输出设备上输出一条消息。

如果现在我们编译并运行这个程序,那么测试将会正常通过,同时一切看上去都非常顺利。但是如果我们修改代码使其报错,那么将会发生什么呢?为了找出错误信息,我们将不得不仔细地盯着屏幕。我们可能不必提供输入信息,但是我们仍然在测试我们自己监控程序输出的能力。我们想要测试的是代码,而不是我们自己!

在Java中,表示错误条件的传统做法是抛出异常。所以,我们要抛出异常来表示测试失败。

与此同时,我们或许还想针对其他尚未编写的Calculator方法运行测试,如subtract或multiply。转向模块化的设计可以使得捕捉和处理异常更为容易,也可以使得以后扩展测试程序更为简单。代码1.3展示了稍好一点的CalculatorTest程序。

代码1.3 稍好一点的CalculatorTest程序

48fde05a51a1ca541811383ec44ebde8d9a47cb5

来看代码1.3,在..Lucene实战1.tif部分,我们把测试转移到了它自己的testAdd方法中。现在要观察测试做了些什么更加容易了。我们稍后也可以增加更多的方法,编写更多的单元测试,而不会使main方法变得更加难以维护。在..Lucene实战2.tif部分,我们修改了main方法,以便在发生错误时输出栈跟踪信息,然后,如果发生任何错误,就抛出一个总结性的异常结束运行。

既然你已经理解了一个简单的应用程序及其测试,那么你就能够发现,即使这种不重要的类及其测试都可以从少量的脚手架代码(scaffolding code)中受益——我们创建脚手架代码来运行和管理测试结果。由于应用程序变得越来越复杂、涉及的测试也越来越多,继续构建和维护我们自己自定义的测试框架已成为一个负担。

接下来,我们退一步,来看一下单元测试框架的一般情况。

1Kent Beck, Extreme Programming Explained: Embrace Change (Reading, MA: Addison-Wesley, 1999)。
本文仅用于学习和交流目的,不代表异步社区观点。非商业转载请注明作译者、出处,并保留本文的原始链接。

相关文章
|
Java 测试技术 Spring
Gradle从0入门到实战系列【八】SpringBoot集成Junit单元测试
JUnit 是一个 Java 编程语言的单元测试框架。JUnit 在测试驱动的开发方面有很重要的发展,是起源于 JUnit 的一个统称为 xUnit 的单元测试框架之一。
1298 1
Gradle从0入门到实战系列【八】SpringBoot集成Junit单元测试
|
域名解析 IDE Java
在 Maven 项目中运行 JUnit 5 测试用例
本文为大家演示了如何如何编写JUnit 5测试用例以及在Maven项目中运行JUnit 5测试用例的过程。
2501 0
在 Maven 项目中运行 JUnit 5 测试用例
|
Java 测试技术 程序员
|
Android开发
IntelIj IDEA运行JUnit Test OutOfMemoryError
好久没看到OutOfMemoryError这种错误了,今天跑测试的时候发现总是报错。针对IDEA需要修改几个配置。 JUnit Test在运行前,IDEA会build整个项目,这个是喜欢eclipse的人最讨厌的地方,因为即便是别的不相干的类没配置好,我的Test也不能跑。
1707 0