主要技术手段
驱动代码,桩代码和Mock代码
驱动代码: 调用被测函数的代码。 在单元测试过程中,驱动模块通常包括调用被测函数前的数据准备、调用被测函数以及验证相关结果三个步骤。
桩代码(Stub): 用来代替真实代码的临时代码。 例如,函数A的内部实现中调用了一个尚未实现的函数B,为了对函数A的逻辑进行测试,那么就需要模拟一个函数B,这个模拟的函数B的实现就是所谓的桩代码。
Mock代码: 和桩代码非常类似,都是用来代替真实代码的临时代码,起到隔离和补齐的作用。
代码结构特征
数据分类处理: 抛开业务逻辑,从代码结构方面看代码,每一次条件判定,每一次嵌套条件判定,都是在对数据做分类处理,不同分类走不同的处理流程。
分类缺陷: 分类遗漏产生缺陷,分类处理逻辑错误,也会产生错误。
实现正确逻辑的三种考虑:
- 正常输入
- 特殊处理的边界输入
- 非法输入的可能,如何处理
类似于等价类测试,以上三点只要处理错误就会产生缺陷。
单元测试用例
输入数据与预计输出
和接口测试类似,但是接口测试只是其中最简单的一种,单元测试用例的输入数据和预计输出要复杂很多。
输入数据:
- 被测函数的输入参数
- 被测函数内部需要读取的全局变量
- 被测函数内部需要读取的成员变量
- 函数内部调用子函数获取的数据
- 函数内部调用子函数改写的数据
预计输出:
- 被测函数的返回值
- 被测函数的输出参数
- 被测函数改写的变量(全局变量和成员变量)
- 被测函数中的更新(文件,数据库,消息队列)
- 单元测试执行
选择:
- 底层模块和核心模块采用单元测试
- 测试框架选型与开发语言相关
- 单元测试代码覆盖率
- 单元测试加入持续集成
自动化:
- 单元测试框架代码自动生成
- 部分输入测试数据自动生成
- 桩代码自动生成
- 被测代码的自动静态分析
- 测试覆盖率的自动统计与分析
难点:
- 紧密耦合代码难以隔离
- 隔离后编译链接运行困难
- 代码本身可测性差
- 无法通过桩代码模拟底层函数