五、从宏观角度考虑单元测试

进行重构以使得代码更为清晰

  • 单元测试可以有效的支持重构,在单元测试保障下,可能的错误会因单元测试的存在而被及时识别。
  • 重构的范围比较大,这里仅说明方法级别的重构。
  • 方法级别的重构的原则是将复杂的,能够隔离的逻辑单独提取,给与明确的方法命名,保证方法内的逻辑简洁,以调高代码的易读性和易测试性。
  • 在进行完方法级别的抽取后,可以考虑将同类型的方法抽取到类中
  • 可以使用IDE提供的工具进行重构,如Eclipse的Refactor
  • 最后,不必过分担心重构所带来的问题,多几个方法或者类对性能的影响微乎其微。与其担心,不如先将代码进行重构,以为后面性能问题暴露后的优化进行准备
  • 清晰的设计是为优化做的最好的准备

一些高层的设计原则

  • 单元测试并非凭空出现的,编写单元测试的难易程度与系统设计息息相关
  • 要尽量将类的职责单一化,一个类的职责越多,越有可能影响其他已经存在的行为
  • 类设计原则 SOLID
    • SRP 
      • Single Responsibility Principle 单一职责原则
      • 类应该仅会由于一种原因发生变更
      • 保持类的体积小,职责单一
    • OCP
      • Open-Close Principle 开闭原则
      • 类应该对扩展开发对修改关闭
      • 尽量减少对类的修改需求
    • LSP
      • Liskov Substitution Principle 里氏代换原则
      • 子类应该代换基类
      • 从客户视角看,子类重写不应破坏父类方法的功能
      • 也即在任何情况下,子类都能够代替父类,从方法角度讲,子类不能破坏父类的功能
    • ISP
      • Interface Segregation Principle 接口隔离原则
      • 客户不应被强制依赖它们不需要的方法
      • 将大的接口类拆分为小的接口类
    • DIP
      • Dependency Inversion Principle 依赖倒置原则
      • 高层模块不应依赖底层模块
      • 高层模块和底层模块都应当依赖抽象
      • 抽象不应依赖细节
      • 细节应该依赖抽象
  • 方法设计原则
    • 命令和行为分离(command-query separation),也即方法要尽量减少副作用,要么查询,要么修改,不要都做
    • 反面教材就是iterator.next()方法,难用,易错,怪异
  • 单元测试的维护成本很高,我们接受它的唯一原因就是它带来了更大的收益
  • 如果单元测试很难写,检查设计先,优化代码先
  • 当系统的设计/代码质量下降,单元测试的维护成本会上升
  • 最后,不断提高的单元测试覆盖率能够提升重构的信心

重构测试

一些常见的单元测试坏味道
  • 不必要的代码,如在单元测试中无需捕获异常,直接抛出即可,JUnit可以自动判断该测试用例为false
  • 缺乏抽象,如重复代码没有抽取,断言没有合并等
  • 无关信息,像编写生产代码一样编写测试代码,注重易读性,扩展性,降低维护成本,增加业务逻辑,持续从单元测试中受益
  • 臃肿的构造函数
  • 多个断言
  • 测试中存在无关的细节
  • 含义不明确

单元测试路线图

  1. 重构代码,提升代码的清晰度和一致性
  2. 重构代码,在设计中支持更大的灵活性
  3. 设计系统以支持Mock
  4. 重构测试降低维护成本并提高易读性 
原文地址:https://www.cnblogs.com/jiyuqi/p/13841625.html