单元测试

  • 单元测试是对软件基本组成单元进行的测试
  • 这里的基本单元不一定是指一个具体的函数或一个类的方法。在具体实现时,也可能对应的是多个文件中的一组函数
  • 单元测试的目的
    • 验证单元代码和详细设计文档的一致性
    • 跟踪详细设计文档中设计的实现,发现详细设计文档中存在的错误
    • 发现在编码过程中引入的错误
      • 和设计不符引入的错误
      • 虽然和设计相符但由于编码出现疏漏导致错误
  • 单元的常见错误
    • 单元接口
      • 被测单元的输入输出参数在个数、属性、顺序上和详细设计中的描述不一致
      • 修改了只做输入用的形式参数,可能会导致数据的错误修改
      • 约束条件通过形式参数来传送,导致函数间的控制耦合增大。耦合是指两个实体相互依赖于对方的一个量度,分为以下几种:
        • 非直接耦合:两个模块之间没有直接关系,它们之间的联系完全是通过主模块的控制和调用来实现的
        • 数据耦合:一个模块访问另一个模块时,彼此之间是通过简单数据参数(不是控制参数、公共数据结构或外部变量)来交换输入、输出信息的。
        • 标记耦合:一组模块通过参数表传递记录信息,就是标记耦合。这个记录是某一数据结构的子结构,而不是简单变量。
        • 控制耦合:如果一个模块通过传递开关、标志、名字等控制信息,明显的控制选择另一模块的功能,就是控制耦合
        • 外部耦合:一组模块都访问同一简单全局变量而不是同一全局数据结构,而且不是通过参数表传递该全局变量的信息,则称之为外部耦合
        • 公共耦合:若一组模块都访问同一个公共数据环境,则它们之间的耦合则称为公共耦合。公共的数据环境可以是全局数据结构、共享的通信区、内存的公共覆盖区等
        • 内容耦合:
          • 一个模块直接访问另一个模块的内部数据
          • 一个模块不通过正常入口转到另一模块内部
          • 两个模块有一部分程序代码重叠(只可能出现在汇编语言中)
          • 一个模块有多个入口
    • 局部数据结构
      • 单元的局部数据结构是最常见的错误来源。在单元工作过程中,必须测试单元内部的数据能否保持完整性,包括内部数据的内容、形式及相互关系不发生错误
      • 单元测试中注意以下几类错误:
        • 不正确或不一致的数据类型说明
        • 使用尚未复制或尚未初始化的变量
        • 错误的初始值或错误的缺省值
        • 变量名拼写错误或书写错误
        • 不一致的数据类型
    • 独立路径
      • 设计测试用例查找由于错误的计算、不正确的比较和不正常的控制流而导致的错误
      • 常见的错误有:
        • 运算的优先次序不正确或误解了运算的有限次序
        • 运算的方式错误
        • 不同数据类型的比较
        • 关系表达式中不正确的变量和比较符
        • “差 1 错”。即不正确的多循环或少循环一次
        • 错误或不可能的循环终止条件
        • 当遇到发散的迭代时不能终止的循环
          • 迭代要谨慎使用,调用层次不能过深,迭代过程中如果涉及到大的变量传递需要使用指针来完成
          • 可能一直递归下去找不到返回的路径,一直发散下去
          • 递归嵌套层次太深,每嵌套调用一次都要消耗堆栈资源,可能会导致递归还未到回归点时,堆栈资源已被耗光
        • 不适当的修改了循环变量等
    • 出错处理
      • 比较完善的单元设计要求能预见出错的条件,并设置适当的出错处理,以便在程序出错时,能对出错程序重新做安排,保证其逻辑上的正确性。
      • 出错处理模块经常出现的错误或缺陷有
        • 出错的描述难以理解
        • 出错的描述不足以对错误定位和确定出错的原因
        • 显示的错误与实际的错误不符
        • 对错误条件的处理不正确
        • 在对错误进行处理之前,错误条件已经引起系统的干预等
      • 单元内的出错处理
        • 对外部接口来的各种可能的情况进行防范处理
        • 对单元内部调用的下层函数的各种可能返回值分别进行处理
    • 边界条件
      • 在 n 次循环的第 n 次,取最大最小值时容易发生错误
      • 特别要注意数据流,控制流中刚好等于、大于、小于确定的比较值时出现错误的可能性
  • 单元测试和集成测试、系统测试的区别
    • 测试方法不同
      • 单元测试属于白盒测试范畴
      • 集成测试属于灰盒测试范畴
      • 系统测试属于黑盒测试范畴
    • 考察范围不同
      • 单元测试主要测试单元内部的数据结构、逻辑控制、异常处理等
      • 集成测试主要测试模块之间的接口和接口数据传递关系,以及模块组合后的整体功能
      • 系统测试主要测试整个系统相对于需求的符合度
    • 评估基准不同
      • 单元测试的评估基准主要是逻辑覆盖率
      • 集成测试的评估基准主要是接口覆盖率
      • 集成测试的评估基准主要是测试用例对需求规格的覆盖率
  • 单元测试环境
    • 在单元测试时,由于单元本身不是一个独立的程序,一个完整的可运行的软件系统并没有构成,所以需要设计一些辅助测试单元。辅助测试单元有两种:驱动单元和桩单元
    • 驱动单元:用来模拟被测单元的上层单元,相当于被测函数的主程序,如 main 函数。它接收测试数据,将相关数据传送给被测单元,启动被测单元,最后再输出实测结果。当被测单元能完成相关功能时,也可以不要驱动单元- 桩单元:用来代替被测单元工作过程中调用的子单元
    • 构造单元的测试环境的主要工作有
      • 构造最小运行调度系统,即驱动单元,用以模拟被测单元的上一级单元
      • 模拟实现单元接口,即单元函数需要调用的其他函数接口,即桩单元
      • 模拟生成测试数据和状态,为单元运行准备动态环境
    • 驱动单元
      • 驱动单元主要完成以下步骤
        • 接收测试数据,包含测试用例输入和预期输出
        • 把测试用例输出传送给要测试的单元,驱动被测单元运行
        • 将被测单元的实际输出和预期输出进行比较,得到测试结果
        • 将测试结果输出到指定位置
      • 类型:顶层函数、非顶层函数
      • 不同接口:函数接口、消息接口、文件接口
      • 输出:返回值、消息、内存、变量、文件
      • 输出参数数目:1 个、多个
    • 桩单元
      • 桩单元的功能是从测试角度模拟被测单元所调用的其他单元。桩单元需要针对不同的输入,返回不同的期望值,模拟不同的功能
      • 类型:自定义函数、系统函数
      • 如果被测函数为底层函数,则不需要设计桩单元
  • 单元测试策略
    • 独立的测试策略
      • 方法:不考虑每个模块与其他模块的关系,为每个模块设计桩模块和驱动模块。每个模块进行独立的单元测试
      • 优点:该方法是最简单,最容易操作的。可以达到高的结构覆盖率。该方法是纯粹的单元测试
      • 缺点:桩函数和驱动函数工作量很大,效率低
    • 自顶向下的测试策略
      • 方法:先对最顶层的单元进行测试,把顶层所调用的单元做成桩模块。其次对第二层进行测试,使用上面已测试的单元做驱动模块。如此类推直到测试完所有模块
      • 优点:可以节省驱动模块的开发工作量,测试效率较高
      • 缺点:随着被测单元一个一个被加入,测试过程将变得越来越复杂,并且开发和维护的成本将增加
    • 自底向上测试
      • 方法:先对模块调用层次图上最底层的模块进行单元测试,模拟调用该模块的模块做驱动模块。然后再对上面一层做单元测试,用下面已被测试过的模块做桩模块。以此类推,直到测试完所有模块
      • 优点:可以节省桩模块的开发工作量,测试效率较高
      • 缺点:不是纯粹的单元测试,底层函数的测试质量对上层函数的测试将产生很大的影响
    • 混合测试
      • 自顶向下和自底向上的测试策略综合了集成的概念,随着单元测试的进行,测试覆盖率会越来越难以保证,并且在每个测试之间必须保证相关单元的正确性。独立的测试策略比较独立,覆盖率容易保证,并且可以并行进行,但工作量最大。一般采用混合方法比较好。
  • 单元测试过程
    • 单元测试计划阶段:完成单元测试计划
      • 计划阶段应当考虑整个单元测试过程的事件表,工作量,任务的划分情况,人员和资源的安排情况,需要的测试工具和测试方法,单元测试结束的标准及验收的标准等,同时还应当考虑可能存在的风险,以及针对这些风险的可能处理方法,并输出《单元测试计划》文档,作为整个单元测试过程的指导
    • 单元测试设计阶段:完成单元测试方法
      • 设计阶段需要考虑对哪些单元进行测试,被测模块之间的关系以及同其他模块之间的关系,具体测试的策略采用哪一种,如何进行单元测试用例的设计、如何进行单元测试代码设计、采用何种工具等,并输出《单元测试方案》文档,用来指导具体的单元测试操作
    • 单元测试实现阶段:完成单元测试用例、单元测试脚本及数据文件
      • 实现阶段需要完成单元测试用例设计、脚本的编写,测试驱动模块的编写,测试桩模块的编写工作,输出《单元测试用例》文档、相关测试代码
    • 单元测试执行阶段:执行单元测试用例,修改发现的问题并进行回归测试,提交单元测试报告
  • 单元测试的原则
    • 原则
      • 对全新的代码或修改过的代码进行单元测试
      • 单元测试根据单元测试计划和方案进行,排除测试的随意性
      • 必须保证单元测试计划、单元测试方案、单元测试用例等经过评审
      • 当测试用例的测试结果与预期结果不一致时,单元测试的执行人员需如实记录实际的测试结果
      • 只有当测试计划中的结束标准达到时,单元测试才能结束
      • 对被测试单元需达到一定的代码覆盖率要求
    • 从组织、技术、流程三个方面保证做好单元测试
      • 组织结构应该保证测试组参加单元测试
      • 加强单元测试流程规范性
        • 制定单元测试的过程定义
        • 单元测试工作产品必须纳入配置管理
        • 必须制定覆盖率指标和质量目标来指导和验收单元测试
        • 加强详细设计文档评审
      • 单元测试者技能的提高
        • 加强对单元测试人员的技能培训
        • 必须引入工具进行辅助
        • 单元测试者加强对被测软件的全面了解
    • 单元测试工具介绍
      • 代码静态分析工具
        • Logiscope(瑞典Telelogic公司)
        • McCabe QA(复杂度分析和基本路径分析,美国McCabe & Association公司)
        • CodeTest(AMC公司)
      • 代码检查工具
        • PC-LINT
        • CodeChk
        • Logiscope
      • 测试脚本工具
        • TCL(Tool Command Language)
        • Python
        • Perl(Practical Extraction and Report Language)
      • 覆盖率检测工具
        • Logiscope
        • PureCoverage(Rational公司)
        • TrueCoverage(Compuware公司)
        • McCabeTest
        • CodeTest
      • 内存检测工具
        • Purify(内存泄漏检查,Rational公司)
        • BoundsCheck(内存越界检查,Compuware公司)
        • CodeTest公司
      • 专为单元测试设计的工具
        • RTRT(Rational公司)
        • Cantata
        • AdaTest
      • 开源自动化框架XUnit
        • CppUnit
        • JUnit
        • DUnit
        • Nunit

欢迎扫码关注微信公众号「一朵儿的软件测试之旅」一起学习交流
在这里插入图片描述

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值