单元测试知识


定义

单元测试是指对软件中的最小可测试单元 进行检查和验证。通常而言,一个单元测试是用于判断每个特定条件(或场景)下某个特定函数的行为,单元测试是由开发写的。执行单元测试是为了证明编写的功能代码与我们期望的一致。

引申概念

针对每个单独的小方法,在于程序其他部分相隔离的情况下进行测试,输入参数,校验出参是否合乎预期。因此,不测数据库操作、不测网络连接、不测依赖调用。以上的场景全部mock掉。

测试方向

自顶向下

此种方式不推荐,其为接口->接口实现类->原子实现类->Dao层。

自底向上

自底向上就是先测试下一层的方法,再测较高一层的方法,较高一层的方法在调用下一层方法的时候,也是mock掉的。方向为Dao层->原子实现类->接口实现类。

具体实现:框架级代码->工具类代码->原子实现类代码->接口实现类代码

特点

测试更充分

单元测试是最底层的测试,是白盒测试,能够测试所有正流程分支和异常分支,是最容易发现BUG的阶段,也能够发现其他测试环节发现不了的BUG,是接口测试和ui自动化测试无法代替的,是不同层次的覆盖。

BUG修复代价最少

单元测试的后继阶段(功能继承测试 UAT测试 上线后的阶段)发现BUG修复的周期很长,修复的代价也更大。

代码自REVIEW

写单元测试的过程,也是一次代码REVIEW的过程。单元测试能促进开发者进行代码审查与优化,并能提高代码可读性。同时还能发现如下一系列问题:返回码错误、分支不可达、冗余的参数和方法、对象转换错误、空指针异常、死循环、日至记录错误、判断逻辑不严密等,并能给出代码健壮性建议。

代码功能更具易用性

编写单元测试将使我们从调用者角度观察、思考,审查功能是否易于调用和可测试的,可降低软件中的耦合性。

回归测试

如果核心功能的代码,单元测试行覆盖率和分支覆盖率足够高,重构后跑一遍单元测试,相关功能都能测试到,就不必担心代码重构时,影响其他功能。

快速定位BUG

如果程序中有BUG,我们运行一次全部单元测试,找到不通过的测试,可以很快的定位对应的执行代码。修复代码后,运行对应的单元测试;如还不通过,继续修改,运行测试,直至测试通过。

白盒测试技术

其中有六种相关技术:语句覆盖->判定覆盖->条件覆盖->判断条件覆盖->组合覆盖->路径覆盖,其测试强度从弱到强,相应的单侧工作量也越来越大。

语句覆盖

程序中每条语句至少执行一次,这样可以很直观的从源代码得到测试用例,无须细分每条判定表达式。但是隐式逻辑分支无法测试。

判定覆盖

每次判定至少一次为真值,有一次为假值,即:程序中每个分支至少执行一次。每次判断的取真、取假至少执行一次。覆盖强度几乎增加一倍,测试用例简单。但是关注焦点是表达式逻辑值,可能会遗漏部分测试路径。

条件覆盖

设计足够多的测试用例,使得判定中的每个条件获得各种可能的结果,即每个条件至少一次为真值,有一次为假值。相对判定覆盖,增加了对符合判定情况的测试,增加了测试路径。需要足够多的测试用例,条件覆盖并不能保证判定覆盖。

判断条件覆盖

设计足够多的测试用例,使得判定中每个天骄爱你的所有可能结果至少出现一次,每个判定本身所有可能结果也至少出现一次。满足判定覆盖准则和田间覆盖准则,弥补了二者的不足。但未考虑条件的组合情况,容易漏、会忽略田间中取或(or)的情况。

组合覆盖

使得每个判定中条件结果的所有可能组合至少出现一次。多重条件覆盖准则满足判定覆盖、条件覆盖和判定/田间覆盖准则。线性的增加了测试用例的数量,也不能不着所有路径被测试。

路径覆盖

覆盖程序中所有可能的路径。可以对程序进行彻底的测试,比前面的五种的覆盖面都广。但是需要设计大量、复杂的测试用例,使得工作量呈指数级增长,特殊路径无法测试。

要求

  • 单元测试应该是全自动执行的,并且非交互式的。
  • 保持单元测试的独立性。
  • 淡雅u你策划四是可以重复执行的,不能受到外界环境的影响。
  • 对于单元测试,要保证测试粒度足够小,有助于精确定位问题。单侧粒度一般是方法级别的,至多是类级别。
  • 核心业务、核心应用、核心模块的增量代码确保单元测试通过。
  • 单元测试的代码必须写在src/test/java,不允许写在业务代码目录下。
  • 单元测试的基本目标:语句覆盖率达到80%,核心模块的语句覆盖率和分支覆盖率都要达到100%。
  • 对于不可测的代码必须做必要的重构,使代码可测,避免为了达到测试要求而写不规范测试代码。
  • 在设计评审阶段,开发人员需要和测试人员一起确定单元测试范围,单元测试最好覆盖所有测试用例。
  • 单元测试作为一种质量保障手段,不建议项目发表后补充淡雅u你测试用例,建议在项目提前完成单元测试。
  • 为了更方便的进行单元测试,业务代码应避免一下情况:构造方法中做的事情过多。存在过多的全局变量和静态方法。存在过多的外部依赖。存在过多的条件语句。
  • 单元测试与开发强相关;单元测试需要维护;

数据准备

数据大致分为三类:正常数据、边界数据、异常数据

测试用例

  • 为系统运行起来而设计用例
  • 为正向测试而设计用例
  • 为逆向测试而设计用例
  • 为代码覆盖率而设计用例
  • 为满足非功能质量要求而设计用例

Junit4

常用注解

  • @Before:初始化方法
  • @After:释放资源
  • @Test:测试方法,在这里可以测试期望异常和超过时间
  • @Ignore:忽略的测试方法
  • @BeforeClass:针对所有测试,只执行一次,且必须为static void
  • @AfterClass:针对所有测试,只执行一次,且必须为static void

执行顺序

  • 一个Junit4的的单元测试用例执行顺序为:@BeforeClass->@Before->@Test->@After->@AfterClass
  • 每一个测试方法的调用顺序:@Before->@Test->@After

Mock

常见的Mock场景

  • 对象:模拟一些在应用中不容易构造或者比较复杂的对象
  • 接口:调用别的接口方法必须mock,达到隔离的效果
  • 静态方法:工具类中的静态方法建议mock,单独测试
  • Dao层方法:Dao层操作数据库的方法必须mock,隔离数据库
  • 私有方法:建议通过共有方法直接覆盖私有方法的方式来测试,也可以将私有方法mock,之后用反射的方式单独测试。

文章作者: 不二
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 不二 !
  目录