测试是最常见的改善治理的活动,软件可以通过很多的方法进行测试,有些测试由开发人员进行,有些更更多的由专门的测试人员进行:

  • 单元测试
  • 组件测试
  • 集成测试
  • 回归测试
  • 系统测试

1、 开发者测试在软件质量中的角色

测试对于绝大多数开发人员来说都是一种煎熬,理由是:

  • 测试的目标与其他开发活动背道而驰,测试的目标是找出错误
  • 测试永远不可能彻底证明程序中没有错误
  • 测试本身并不能改善软件的质量
  • 测试时要求你假设会在代码里面找到错误

但是,开发者必须期望代码里有错误,并且找出代码错误的人是你自己。随着项目规模的增大,开发者测试所耗费的时间百分比会更少。开发者测试的结果可以用来评估正在开发产品的可靠性,可以指导对软件的修正。

2、开发者测试的推荐方法

  • 系统化的开发者测试方法包含的要点:

    • 对每项相关的需求进行测试,以确保需求都已经实现
    • 对每个相关的设计关注点进行测试,以确保设计已经被实现
    • 用基础测试来扩充针对需求和设计的详细测试用例
    • 使用一个检查表,其中记录着你在本项目中所犯的,以及在过去项目中犯下的错误类型
  • 测试先行的理由:

    • 开始编写代码之前先写测试用例,并不比之后在写要多花功夫,只是调整了测试用例编写活动的工作顺序。
    • 可以更早的发现缺陷同时也更容易修正他们
    • 将迫使你在开始写代码之前思考需求和设计,催生更高质量的代码
    • 能更早的把需求上的问题暴露出来,因为对于一个赵高的需求,写出测试用例是一件困难的事情
    • 保存了最初编写的测试用例,并非要先进行测试,可以选择最后进行测试
  • 开发者测试的局限性

    • 开发者测试倾向于“干净测试”
    • 开发者测试对覆盖率有过于乐观的估计
    • 开发者测试往往会忽略一些更复杂的测试覆盖率类型

3、测试技巧锦囊

测试是不完整的,即使一个简单的程序,测试用例的组合也是十分庞大的,不可能测试所有的情况。通过测试证明程序的正确性是不可能的。测试的窍门在于选择那些最有可能找到错误的测试用例。

  • 结构化基础测试

    结构化基础测试的思想是需要测试程序中的每一条语句至少一次,如果语句是一个逻辑语句(if/while),需要根据表达式的复杂程度修改测试,确保这个语句完全经过了测试。

  • 数据流测试

    数据的三种状态:

    • 已定义
    • 已使用
    • 已销毁

    描述变量进行某种操作之前或之后,控制流进入或退出某个子程序的状态的术语:

    • 已进入
    • 已退出

    数据状态的组合:

    • 已定义-已定义
    • 已定义-已退出
    • 已定义-已销毁
    • 已进入-已销毁
    • 已进入-已使用
    • 已销毁-已销毁
    • 已销毁-已使用
    • 已使用-已定义

    编写数据测试用例的关键是要对所有可能的定义-使用路劲进行测试。

  • 等价类划分

如果两个用例揭示的错误完全相同,则只需要一个就够了。“等价类划分”概念是这一想法的严格表达形式,应用它有助于减少所需用例的数量。

  • 猜测错误

    测试错误是一种寻找代码中错误的不太规矩的、启发式的方法。猜测可以基于直觉或者过去的经验。

  • 边界值分析

    边界值分析的思想就是写一些测试永烈来测试边界值的条件。边界值分析也适用于允许的最大值、最小值。

  • 几类坏数据

    • 数据太少(没有数据)
    • 太多的数据
    • 错误的数据情况(无效数据)
    • 长度错误的数据
    • 未初始化的数据
  • 几类好数据

    • 正常的情形-大陆正中间,所期望的值
    • 最小的正常局面
    • 最大的正常局面
    • 与旧数据的兼容性
  • 采用容易手工检查的测试用例

    当你试着手工计算一个奇怪数组成的表达式的结果时,出现错误的几率和你在程序中发现错误的几率差不多。简单的数值会让你手工计算时倍感轻松,并且,奇怪的数值发现错误的几率不会比其他数值高。

4、典型错误

  • 错误和代码之间的普遍关系:

    • 80%的错误存在于祥明20%的类或者子程序当中
    • 50%的错误被发现存在5%的类当中
  • 错误分类数据的启发

    • 大多数错误的影响防卫是相当有限的
    • 许多错误发生在构建的范畴职位
    • 大多数的构建期错误是编程人员的失误造成的
    • 笔误(拼写错误)是一个常见的问题根源
    • 研究程序员所犯错误原因时,错误理解设计这条会经常出现
    • 大多数错误都很容易修正
    • 总结所在组织中国对付错误的经验
  • 不完善的构建英翻错误所占的比例

    • 小型项目里,构建中的缺陷占了所有错误的大多数
    • 无论项目规模如何,构建缺陷至少占了总缺陷的35%
    • 修正构建错误的代价虽然比修正需求和设计错误相对低廉,但从绝对值来看仍然是高昂的
  • 减少测试用例中错误的数量

    • 检查你的工作
    • 开发软件的时候就要计划好测试用例
    • 多留你的测试用例
    • 将单元测试纳入测试框架

5、测试支持工具

  • 为测试各个类构造脚手架
  • diff工具
  • 测试数据生存器
  • 覆盖率监视器
  • 数据记录器/日志记录器
  • 符号调试器
  • 系统干扰器

    • 内存填充
    • 内存抖动
    • 选择性内存失败
    • 内存访问检查(边界检查)
  • 错误数据库

6、改善测试过程

  • 有计划的测试
  • 重新测试(回归测试)
  • 自动化测试

    • 自动化测试发生错误的几率比手动测试要小
    • 一旦把一个测试自动化,秩序稍下功夫就很容易在项目的剩余部分继续实施自动化
    • 自动化的测试可以频繁运行,看看新check in的代码是否破坏了原有的程序
    • 自动化测试可以提高问题刚产生就被发现的可能性
    • 自动化测试能够提升快速发现修改所引入错误的几率
    • 自动化测试在那些新的、不稳定的技术环境挡住特别有价值,因为它提早西施了环境改变对系统的影响

7、保留测试记录

需要收集的数据:

  • 缺陷的管理方面描述(报告日期、报告人、描述或标题、编号、修正日期等)
  • 问题的完整描述
  • 浮现错误所需要的步骤
  • 绕过该问题的建议
  • 相关的缺陷
  • 问题的严重程度
  • 缺陷根源:需求、设计、编码还是测试
  • 编码缺陷的分类
  • 修正错误所改变的类和子程序
  • 缺陷所影响的代码行数
  • 查找错误所花费的小时数
  • 修正错误花费的小时数

测试数据分析:

  • 每个类中的缺陷数目,从最糟糕的类到最好的类依次列出,如果类的规模不同,可能需要对数字进行归一化处理
  • 按照统一的方式列出每个子程序的缺陷数
  • 发现一个错误的评价所需要花费的测试时间
  • 每个测试用例所发现缺陷的平均数
  • 修正一个缺陷花费的评价编程时间
  • 全部测试用例的代码覆盖率
  • 在各个严重级别中未处理缺陷的数量

更多有关《代码大全 2》的读书笔记,请关注 :
http://tabalt.net/blog/code-complete-2-reading-notes/

本文链接:http://tabalt.net/blog/cc2-developer-testing/,转载请注明。