目录
前言
一个质量过硬的软件系统,除了显示功能性需求以外,其他的非功能性需求即隐式功能性需求也是极其关键的。
显示功能性需求:软件本身需要实现的具体功能。
非功能性需求:从软件测试的维度看,非功能性需求主要涉及安全性、性能以及兼容性三大方面。
01-测试的不可穷尽性
穷尽测试:指包含了软件输入值和前提条件所有可能组合的测试方法,完成穷尽测试的系统里应该不残留任何未知的软件缺陷。
但是测试任何软件、硬件,不可能完全没有问题,这就是所谓的测试的不可穷尽性。
02-如何设计好的测试用例
“好的”测试用例一定是一个完备的集合,它能够覆盖所有等价类以及各种边界值,跟能否发现缺陷无关。
“好的”测试用例必须具备的三个特征:
a.整体完备性:“好的”测试用例一定是一个完备的整体,是有效测试用例组成的集合,能够完全覆盖测试需求。
b.等价类划分的准确性:指的是对于每个等价类都能保证只要其中一个输入测试通过,其他输入也一定测试通过。
c.等价类集合的完备性:需要保证所有可能的边界值和边界条件都已经正确识别。
理论的设计测试用例方法:等价类划分法、边界值分析法、错误推测法、因果图、判定表驱动分析法、正交实验设计法、功能图分析法、场景设计法、形式化法、扩展有限状态机方法。
03-单元测试
单元测试:对软件中的最小可测试单元在与程序其他部分相隔离的情况下进行检查和验证的工作,这里的最小可测试单元通常是指函数或者类。要做到代码功能逻辑正确,必须做到分类正确并且完备无遗漏,同时每个分类的处理逻辑必须正确。
单元测试的用例是一个“输入数据”和“预计输出”的集合。
“输入数据”包含:
(1)被测试函数的输入参数
(2)被测试函数内部需要读取的全局静态变量
(3)被测试函数内部需要读取的成员变量
(4)函数内部调用子函数获得的数据
(5)函数内部调用子函数改写的数据
(6)嵌入式系统中,在中断调用时改写的数据
“预计输出”包含:
(1)被测试函数的返回值
(2)被测试函数的输出函数
(3)被测试函数所改写的成员变量
(4)被测试函数所改写的全局变量
(5)被测试函数中进行的文件更新
(6)被测试函数中进行的数据库更新
(7)被测试函数中进行的消息队列更新
驱动代码是用来调用被测函数的,桩代码和Mock代码是用来代替被测函数调用的真实代码的。
驱动代码指调用被测函数的代码,驱动模块通常包括调用被测函数前的数据准备、调用被测函数以及验证相关结果三个步骤。
桩代码是用来代替真实代码的临时代码,桩代码的应用首先起到了隔离和补齐的作用,使被测代码能够独立编译、链接、并独立运行。桩代码还具有控制被测函数执行路径的作用。
桩代码和Mock代码的本质区别是:测试期待结果的验证。
Java最常用的单元测试框架是Junit和TestNG;C/C++最常用的单元测试框架是CppTest和Parasoft C/C++test
单元测试的代码覆盖率:Java的JaCoCo,JavaScript的Istanbul
04-自动化测试
a.自动化测试的优势
(1)自动化测试可以替代大量的手工机械重复性操作,测试工程师可以把更多的时间花在更全面的用例设计和新功能的测试上;
(2)自动化测试可以大幅提升回归测试的效率,非常适合敏捷开发过程;
(3)自动化测试可以更好地利用无人值守时间,去更频繁地执行测试,特别适合现在非工作时间执行测试,工作时间分析失败用例的工作模式;
(4)自动化测试可以高效实现某些手工测试无法完成或者代价巨大的测试类型,比如关键业务 7×24 小时持续运行的系统稳定性测试和高并发场景的压力测试等;
(5)自动化测试还可以保证每次测试执行的操作以及验证的一致性和可重复性,避免人为的遗漏或疏忽。
b.自动化测试的缺点
(1)自动化测试并不能取代手工测试,它只能替代手工测试中执行频率高、机械化的重复步骤。
(2)自动测试远比手动测试脆弱,无法应对被测系统的变化。
(3)自动化测试用例的开发工作量远大于单次的手工测试,所以只有当开发完成的测试用例的有效执行次数大于等于 5 次时,才能收回自动化测试的成本。
(4)手工测试发现的缺陷数量通常比自动化测试要更多,并且自动化测试仅仅能发现回归测试范围的缺陷。
(5)测试的效率很大程度上依赖自动化测试用例的设计以及实现质量,不稳定的自动化测试用例实现比没有自动化更糟糕。
(6)实行自动化测试的初期,用例开发效率通常都很低,大量初期开发的用例通常会在整个自动化测试体系成熟,和测试工程师全面掌握测试工具后,需要重构。
(7)业务测试专家和自动化测试专家通常是两批人,前者懂业务不懂自动化技术,后者懂自动化技术但不懂业务,只有二者紧密合作,才能高效开展自动化测试。
(8)自动化测试开发人员必须具备一定的编程能力,这对传统的手工测试工程师会是一个挑战。
c.什么样的项目适合自动化测试?
(1)需求稳定,不会频繁变更
(2)研发和维护周期长,需要频繁执行回归测试
(3)需要在多种平台上重复运行相同测试的场景
(4)某些测试项目通过手工测试无法实现,或者手工成本太高
(5)被测软件的开发较为规范,能够保证系统的可测试性
(6)测试人员已经具备一定的编程能力
05-测试覆盖率
测试覆盖率通常被用来衡量测试的充分性和完整性,从广义的角度来讲,测试覆盖率主要分为两大类,一类是面向项目的需求覆盖率,另一类是更偏向技术的代码覆盖率。
需求覆盖率:指测试对需求的覆盖程度,通常的做法是将每一条分解后的软件需求和对应的测试建立一对多的映射关系,最终目标是保证测试可以覆盖每个需求,以保证软件产品的质量。
代码覆盖率:至少被执行了一次的条目数占整个条目数的百分比。
最常用的三种代码覆盖率指标:
(1)行覆盖率:又称为语句覆盖率,指已经被执行到的语句占总可执行语句的百分比。
(2)判定覆盖:又称为分支覆盖,用以度量程序中每一个判定的分支是否都被测试到了,即代码中每个判断的取真分支和取假分支是否各被覆盖至少各一次。
(3)条件覆盖:判定中的每个条件的可能取值至少满足一次,度量判定中的每个条件的结果TRUE和FALSE是否都被测试到了。
实现代码覆盖率的统计,最基本的方法就是注入。注入是在被测代码中自动插入用于覆盖统计的探针代码,并保证插入的探针代码不会给原代码带来任何影响。
根据注入目标的不同,可以分为源代码注入和字节码注入。
根据注入发生的时间点,字节码注入可分为两大模式:On-The-Fly注入模式和Offline注入模式。
06-软件缺陷报告
缺陷报告是测试工程师和开发工程师交流沟通的重要桥梁,也是测试工程师日常工作的重要输出。
一份高效的软件缺陷报告,应该包括:缺陷标题、缺陷概述、缺陷影响、环境配置、前置条件、缺陷重现步骤、期望结果和实际结果、优先级和严重程度、变通方案、根原因分析、附件。
07-测试计划
一份好的测试计划需包括:测试范围、测试策略、测试资源、测试进度和测试风险预估。
(1)测试范围:被测对象以及主要的测试内容。测试范围中需要明确“测什么”和“不测什么”。
(2)测试策略:需要明确“先测什么后测什么”和“如何来测”这两个问题。测试策略会要求我们明确测试的重点,以及各项测试的先后顺序。测试策略还需要说明,采用什么样的测试类型和测试方法。
(3)测试资源:需要明确“谁来测”和“在哪里测”这两个问题。
(4)测试进度:主要描述各类测试的开始时间,所需工作量,预计完成时间,并以此为依据来建议最终产品的上线发布时间。
(大部分公司还是采用传统瀑布模型,没有采用行为驱动开发(BDD),测试进度完全依赖于开发完成并递交测试版本的时间)
(5)测试风险预估:通常需求变更、开发延期、发现重大缺陷和人员变动是引入项目测试风险的主要原因。在制定测试计划时,要预估整个测试过程中可能存在的潜在风险,以及当这些风险发生时的应对策略。
08-软件测试工程师的核心竞争力
作为测试人员,必须要深入理解业务,但是业务知识不能等同于测试能力。
目前的测试工程师分为两大类别,一类是做业务功能测试的,另一类是做测试开发的。
传统测试工程师应该具备的核心竞争力
a.测试策略设计能力:对于各种不同的被测软件,能够快速准确地理解需求,并在有限的时间和资源下,明确测试重点以及最适合的测试方法的能力。
(1)测试要具体执行到什么程度
(2)测试需要借助于什么工具
(3)如何运用自动化测试以及自动化测试框架,以及如何选型
(4)测试人员资源如何合理分配
(5)测试进度如何安排
(6)测试风险如何应付
b.测试用例设计能力:无论对于什么类型的测试,都能设计出高效地发现缺陷,保证产品质量的优秀测试用例。
c.快速学习能力
(1)对不同业务需求和功能的快速学习与理解能力
(2)对于测试新技术和新方法的学习与应用能力
d.探索性测试思维:测试工程师在执行测试的过程中不断学习被测系统,同时结合基于自己经验的错误猜测和逻辑推理,整理和分析出更多的有针对性的测试关注点。
e.缺陷分析能力
f.自动化测试技术
g.良好的沟通能力
测试开发工程师的核心竞争力
a.测试系统需求分析能力
b.更宽广的知识体系