写不好单元测试的情况有很多,很多时候我们也是被需求压着身不由己的就开始 “ 胡编乱写” 了。甚至有的时候我们都不知道这个项目可以运行多长时间,项目刚发布完就可能进入到另一个项目的开发周期中,周而复始,更没有时间写单元测试了。
开发人员有一万种理由不写单元测试:
当然不只是单元测试,其实开发连注释都不写的 😂🤣😂。
1. 代码质量
单元测试提高了代码的质量。在实际编码之前编写测试会让你去更多的思考方法或者对象的边界,使您编写更好的代码。
2. 及早发现软件缺陷
问题是在早期阶段发现的。由于单元测试是由在集成之前测试单个代码的开发人员执行的,因此可以很早就发现问题,并且可以在不影响其他代码的情况下解决问题。这既包括开发者实现中的bug,也包括单元规范中的缺陷或缺失部分。
3. 易于重构
完善的单元测试可以验证在重构代码或者更新某些依赖的情况下,确保整个系统依然能正常的工作。当然如果重构已经改变原来的整体逻辑,单元测试也要跟着改动
当开发者向软件添加越来越多的功能时,有时需要更改旧的设计和代码。然而,更改已经测试过的代码既有风险又代价高昂。如果我们有适当的单元测试,那么我们就可以自信地进行重构。
4. 简化调试过程
单元测试有助于简化调试过程。如果测试失败,那么只需要调试代码中的最新更改。
5. 提供文档
单元测试提供了系统的文档。希望了解单元提供什么功能以及如何使用它的开发人员可以查看单元测试,以获得对单元接口(API)的基本理解。
6. 设计
编写测试首先迫使您在编写代码之前仔细考虑您的设计以及它必须完成的任务。这不仅能让你集中注意力,还能让你创造更好的设计。测试一段代码迫使您定义该代码负责什么。如果您可以很容易地做到这一点,那就意味着代码的职责定义良好,因此它具有很高的内聚性。
当然有兴趣的可以看看「测试驱动开发 TDD」
7. 降低成本
由于bug很早就被发现了,单元测试有助于降低bug修复的成本。想象一下在开发的后期阶段,比如在系统测试或验收测试期间发现的bug的成本。当然,较早检测到的bug更容易修复,因为稍后检测到的bug通常是许多更改的结果,并且您不知道是哪一个导致了bug。
上面讲了这么多啰里啰嗦的问题,那我们应该怎么写呢?首先我们要明确我们写单元测试的目的和原则:
目的
原则
注意: 以下代码使用 Java 8 和 Maven 环境下运行,其他环境不保证不出错
放弃写 main 和 sysout 吧 😏
比如我们写了一个工具类(为了展示方便,删除了具体的实现),这是几个比较常用的
比如我们可以看到很多通过直接在 StringUtil 里面通过 main 方法来测试一下各个方法能不能用,比如这样:
这样的测试有意义吗?或许当时写代码的时候确实可以用,但是如何检验正确性呢?如果重构的时候,如何发现已经和原来的行为不一致了呢?
使用 JUnit5 来进行简单的测试
What is JUnit 5?
Unlike previous versions of JUnit, JUnit 5 is composed of several different modules from three different sub-projects.
JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage
The JUnit Platform serves as a foundation for launching testing frameworks on the JVM. It also defines the API for developing a testing framework that runs on the platform. Furthermore, the platform provides a Console Launcher to launch the platform from the command line and a JUnit 4 based Runner for running any on the platform in a JUnit 4 based environment. First-class support for the JUnit Platform also exists in popular IDEs (see IntelliJ IDEA, Eclipse, NetBeans, and Visual Studio Code) and build tools (see Gradle, Maven, and Ant).
JUnit Jupiter is the combination of the new programming model and extension model for writing tests and extensions in JUnit 5. The Jupiter sub-project provides a for running Jupiter based tests on the platform.
JUnit Vintage provides a for running JUnit 3 and JUnit 4 based tests on the platform.
JUnit 是一个在 Java 比较基础的单元测试框架,主要为了单元测试而生,现在已经到了 JUnit 5, 这里也主要使用 JUnit 5,而不是 JUnit 4。
第一步:引入依赖
这里的版本随意,能用就行
第二步:生成测试代码
在 IDEA 中,如果要为某个类或者方法写单元测试很简单,直接在指定的类或者方法 , 即可弹出生成代码的快捷提示,选择 Test 即可,这里选择 firstNonNull,hasText,commonPrefix 来测试一下。
单元测试图片
自动生成的代码如下(如果你熟悉了就可以自己手写,但是 IDEA 能生成,我就不手写了),被标记 @Test 的方法可以单独测试执行,如果你在 IDEA 上可以看到侧边栏有绿色的带箭头的小圆圈,你可以点击对应的执行 run 或者 debug
第三步:使用 JUnit 5 写一些代码
在这里可以点 class 上的绿色按钮来运行下面的全部测试,也可以选择指定的进行测试。
这样一个最简单的单元测试就完成了,里面用到了: (必需) 标记这是一个需要测试的方法; (可选)为测试方法或者类起一个好看的名字或者描述; 通过一系列的断言来判定结果是否正确,这步写不写代码都能通过,但是应该必须写,否则和 sout 有什么区别呢?
通过这三个的组合使用就能完成一系列的简单的单元测试,下面来看下 具体支持什么判定操作。其提供了 282 个方法,其中大部分有重载,这里不再展示所有的重载方法,重载的方法只取最大的那个展示一下
以下内容来自于 org.junit.jupiter.api.Assertions 类中方法
参数说明:message 失败后提示的信息;expected 预期的结果;actual 实际的结果;
代码实现其实是只要 expected 和 actual 不相等就抛异常
在上面的例子中,使用了 、、、 的使用,其他的也可以各自尝试一下,使用方法相同。
上面介绍一下 JUnit 5 的简单用法,通过这种简单的使用,可以测试绝大部分无三方依赖(数据库、三方服务)的代码,在框架类项目中 JUnit 可以就能满足了。在业务项目中,往往情况更加复杂,需要一些其他的辅助工具来完成单元测试。下篇文档会介绍一下其他功能的使用。
常见工具
版权声明:
本文来源网络,所有图片文章版权属于原作者,如有侵权,联系删除。
本文网址:https://www.mushiming.com/mjsbk/5256.html