免费注册


如何写好单元测试?

2022-03-15 人浏览

一、单元测试简介

单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。对于单元测试中单元的含义,一般来说,要根据实际情况去判定其具体含义,如C语言中单元指一个函数,Java里单元指一个类,图形化的软件中可以指一个窗口或一个菜单等。总的来说,单元就是人为规定的最小的被测功能模块。单元测试是在软件开发过程中要进行的最低级别的测试活动,软件的独立单元将在与程序的其他部分相隔离的情况下进行测试。

1、单元测试是一种验证行为。

程序中的每一项功能都是测试来验证它的正确性。它为以后的开发提供支援。就算是开发后期,我们也可以轻松的增加功能或更改程序结构,而不用担心这个过程中会破坏重要的东西。而且它为代码的重构提供了保障。这样,我们就可以更自由的对程序进行改进。

2、单元测试是一种设计行为。

编写单元测试将使我们从调用者观察、思考。特别是先写测试(test-first),迫使我们把程序设计成易于调用和可测试的,即迫使我们解除软件中的耦合。

3、单元测试是一种编写文档的行为。

单元测试是一种无价的文档,它是展示函数或类如何使用的最佳文档。这份文档是可编译、可运行的,并且它保持最新,永远与代码同步。

4、单元测试具有回归性。

自动化的单元测试避免了代码出现回归,编写完成之后,可以随时随地的快速运行测试。单元测试步骤如图所示:

二、单元测试的重要性

假如,A负责开发接口,B负责开发具体的业务。B会调用A开发的接口,但由于种种原因,A开发的接口可能存在一些 bug。在没有单元测试的情况下,这些 bug往往都是由接口的使用者也就是B发现。这无形中给B增加了额外的工作量,因为保证接口质量的工作本该属于A。假设A还是一个比较粗心的人,其中额外增加的时间成本会更大(实际开发中经常遇到)。所以A需要做单元测试以保证这些接口的确具备接口文档中所描述的功能,且能正常执行。

经验表明一个尽责的单元测试方法将会在软件开发的某个阶段发现很多的Bug,并且修改它们的成本也很低。在软件开发的后期阶段,Bug的发现并修改将会变得更加困难,并要消耗大量的时间和开发费用。无论什么时候作出修改都要进行完整的回归测试,在生命周期中尽早地对软件产品进行测试将使效率和质量得到最好的保证。在提供了经过测试的单元的情况下,系统集成过程将会大大地简化。开发人员可以将精力集中在单元之间的交互作用和全局的功能实现上,而不是陷入充满很多Bug的单元之中不能自拔。

开发一个软件的缺陷成本随时间增大而增大,所以应尽早的发现问题并改正,如图所示:

三、如何写好单元测试

1、保持测试代码的紧凑和可读性

要做到这一点,应该要进行毫不留情的重构,就像对生产代码应该做的那样。否则让测试代码随着时间腐化,就是在测试里面制造可怕的遗留代码。如果测试不能很容易重构,那么生产代码也很难重构,从而导致生产系统的遗留代码。

2、测试覆盖尽可能多的范围

单元测试需要覆盖尽可能多的范围,包括:正面所有情景、负面所有情景、临界值、特殊值。

3、测试数据可配置

测试数据大致分为两种:变化的和不变化的,对于不变的测试数据,我们完全可以写在单元测试用例代码中。而对于测试数据一直在变,并且测试数据量比较大的时候可以使用测试数据外部化将数据放在测试用例的外部进行统一管理。

我们可以将一个单元测试用例中的测试数据统一放在一个CSV文件中,通过比如junit5中的参数测试注解@ParameterizedTest和引入CVS文件的注解@CsvFileSource并指定其中的resources属性指定CSV文件,numLinesToSkip = n 属性指定从第n+1行开始。这样就可以通过一个CSV文件统一管理一个单元测试用例中的数据。测试如图所示:

Csv文件如图所示:

 

4、代码规范化

1)代码在保证质量的前提下尽量简洁。

2)单元测试中可以将一些可重用的代码抽象出来,提高代码的复用性。

3)测试类测试方法起名规范化。测试类一般是“类名+Test后缀,测试方法也是类似,测试方法名+Test后缀

4)每个测试方法对被测试方法的功能断言不宜过多。如果一个方法需要多个断言进行测试,我们可以进行大致分类,将其分到两个测试方法中,这样可以细粒度的进行测试。

5、注意测试代码覆盖率

一个设计好的单元测试,其代码测试覆盖率也是很高的,并不要求100% 的测试代码覆盖率,但是高覆盖率的代码包含未检测到的错误的几率要低,因为其更多的源代码在测试过程中被执行。

6、代码依赖复杂时,使用mock模拟接口调用

mock是在测试过程中,对于一些不容易构造/获取的对象,创建一个mock对象来模拟对象的行为。

 

写单元测试能够避免一些粗心或是难以察觉的bug,优秀的单元测试可以充当接口文档的作用,减少许多不必要的沟通成本。此外还能方便代码的重构,使设计代码的思路更加清晰。


上一篇: 行业云说丨浪潮矿业云:云数共舞 打造智能矿山数字底座
下一篇: 数据仓库概述(一)

相关文章