单元测试基础

单元测试的定义

定义

单元测试(又称为模块测试,Unit Testing)是针对程序模块(软件设计的最小单位)来进行正确性检验的测试工作

时机

单元测试和编码同步进行,但在测试驱动开发(TDD)中,强调测试在先,编码在后

单元测试一般由开发人员完成,QA人员辅助

目标

输入和输出对应正确

内部数据保持完整性,内部数据的形式、内容、相互关系

边界值正确处理

满足特定的逻辑覆盖

单元测试的必要性

测试越早介入越好

分析、设计、编码阶段 缺陷比例 10%、40%、50%

软件生命周期阶段,越往后,bug产生的成本越高

编码过程中,每写1000行代码会犯几十个错误

编程和编译结束后,每1000行代码中大约残留2-6个bug

寻找和解决BUG的代价占总体开发时间的30%-60%

为什么程序员不愿做单元测试:

  • 不愿做 没有做单元测试习惯,没有意愿

  • 没时间 项目周期短,基于敏捷开发的节奏越来越快 写单元测试要花很多时间

  • 做不了 代码耦合性高,开展困难

  • 做不好 要达到较高的代码覆盖率很困难

程序员心理:

  • 写单元测试导致不能按时完成任务,推迟项目进度

  • 单元测试价值不高,完全是浪费时间

    长期来看,相比没有单元测试的项目,有单元测试的项目在开发周期中更省时间

  • 业务逻辑简单,不值得写单元测试

    需求会变化,需求文档、代码注释往往不会更新。单元测试可以记录需求变更

    代码编写者去写单元测试比其他人更完善、更准确

    代码维护

    集成测试

  • 不知道怎么编写单元测试

    • 为所有类编写单元测试
    • 学会使用断言
    • 最大化测试覆盖率
    • 避免重复的测试代码
    • 不依赖测试方法的执行顺序
  • 项目前期尽量写单元测试,越到后期越失控

  • 项目没有要求,所以不写

代码如何测

评价标准:代码覆盖率

代码覆盖的步骤:

  • 源代码转为流程图,流程图可以直观的描述代码逻辑
  • 分析流程图,选择需要覆盖的代码
  • 确定测试数据,生成测试用例

白盒测试方法:

  • 语句(statement)覆盖
  • 分支(branch)覆盖/判定(decision)覆盖
  • 条件(condition)覆盖
  • 判定/条件覆盖
  • 条件组合覆盖

语句覆盖

语句覆盖 = (被执行的语句数量/总的语句数量)* 100%

达到100%的语句覆盖很困难

  • 不可达代码
  • 处理错误代码(处理异常)
  • 小概率事件

分支/判定覆盖

忽略了表达式内的条件,不能发现每个条件的错误

条件覆盖

确保每个条件取True和False各一次,可以检查每个原子条件,不能保证所有判断分支都覆盖

判定/条件覆盖

判定条件中的所有条件可能至少执行一次取值,同时,所有判定的可能结果至少执行一次。判定覆盖和条件覆盖的组合

条件组合覆盖

使得每个判定的所有可能的条件取值组合至少执行一次

可满足分支覆盖,也满足语句覆盖

覆盖率

基本准则:

  • 覆盖率部署目的,只是一种手段
  • 不可能针对所有的覆盖率去测试
  • 只考虑一种覆盖标准不恰当
  • 不要追求绝对100%覆盖率

其它准则:

  • 使用最少的测试来达到最大的覆盖
  • 要考虑测试质量,兼顾效益、成本
  • 软件变化需要更新相应的覆盖

代码评审

通过阅读代码来检查软件是否符合编码规范,是否符合代码质量标准

评审内容:

  • 编码规范问题:命名不规范、magic number、System.out…
  • 代码结构问题:重复代码、巨大的方法和类、分层不当
  • 工具、框架使用不当:Spring、Hibernate、AJAX
  • 实现问题:错误验证、异常处理、事务划分、线程、性能、安全、代码过于复杂、代码可读性不佳、扩展性不好
  • 测试问题:测试覆盖率不高、可测试性不好

代码评审中的问题:

  • 低级问题 命名规范和代码风格
  • 中级问题 可重用性问题、控制结构和逻辑问题
  • 高级问题 性能、安全、冗余、功能问题、错误处理、可测量性问题

检查点:

路径测试:

  • 误解或用错了算符优先级
  • 混合类型运算
  • 变量初值错
  • 精度不够
  • 表达式符号错误
  • 其它

数据结构测试:

  • 变量无初值
  • 不适合或者不相容的类型说明
  • 变量初始化或者默认值有错
  • 不正确的变量名或从未被使用过
  • 出现上溢或下溢地址异常
  • 其它

模块接口测试:

  • 输入的实际参数与形式参数是否一致
  • 调用其它模块的实际参数和被调模块的形参是否一致
  • 全程变量的定义在各模块是否一致
  • 外部输入、输出
  • 文件、缓冲区、错误处理
  • 其它

单元边界条件测试:

  • 普通合法数据的处理
  • 普通非法数据的处理
  • 边界值内合法边界数据的处理
  • 边界值外非法边界数据的处理
  • 其它

单元容错测试:

  • 输出的出错信息难以理解
  • 记录的错误和实际不相符
  • 异常处理不当
  • 未提供足够的定位出错信息
  • 其它