《软件测试艺术》按个人思路整理的重点内容,补充了实际项目中的测试经验教训
文章目录
- 一、概念
- 测试
- 测试原则
- 测试的分类
- 测试权衡要素---测试效率/测试覆盖率/测试框架引入
- 用例设计编码原则---代码质量/划分粒度/执行速度/执行独立性/自校验/健壮性
- 三、测试用例设计 之 白盒/黑盒 手段
- 黑盒测试
- (1)等价类划分---典型值
- (2)边界值分析---边界及异常边界
- (3)因果图分析---输入条件组合
- (4)错误猜测---经验与直觉推测异常场景
- 白盒测试
- 语句 / 判定 / 条件 / 判断条件 / 多重条件 / 路径 覆盖
- 四、常见测试用例划分
- 1、功能测试-单元测试/模块测试/集成测试
- 2、性能测试-接口耗时/cpu内存等资源占用/编译镜像size
- 3、异常测试-接口异常参数/模糊测试/异常流程测试(如ctrl+c后资源回收)
- 4、压力测试-切换流程压测/高频接口压测/并发行为压测/最大负载场景
- 5、典型场景-重点场景/基础场景/最大功能叠加场景
- 6、debug手段测试-调试命令/proc打印/报错和info信息
- 五、项目测试经验总结
- 1、开发人员测试效率思考---开发人员该如何测试?有哪些优势/劣势
- 2、测试观念与团队执行思考---关于团队的测试能力提升 和 开发测试氛围培养
一、概念
测试
测试是为了发现错误而执行程序的过程。一个成功的测试用例,通过诱发程序发生错误,可以在咋混个方向上促进程序质量改进。就像医生给病人看病检查,没有异常并不一定是一次成功的测试,准确发现问题才是。
测试原则
1、对预期输出或者结果有明确的定义。
2、避免测试自己编写的程序。
//思维转变,开发人员常对测试理解不够,会陷入思维约束,难以“破坏性”测试
3、编写软件的组织不应当测试自己编写的程序。
//与上一个类似,编写组织难以客观测试,度量时间和功能特性容易,度量可靠性极其困难,常应为进度压缩测试时间
4、应该彻底检查每个测试的执行结果。
5、用例要覆盖无效和未预期的输入。
6、测试不光是测试程序 ‘应该做的’,还要检查 是否 ‘做了不应该做的’。
7、避免测试用例用后即弃(除非一次性软件)
8、测试计划的时候 不应该 假定不会发现错误,要预留问题应对。
9、程序中部分存在更多问题可能性,与 该部分已发现错误成正比。
10、软件测试是一项 创造性、智力挑战的工作。
测试的分类
(1)从是否关注内部实现—黑盒(不关注代码实现)/白盒(根据内部实现流程设计)/灰盒(介于两者之间)
(2)从代码是否需要执行—静态测试(一些静态扫描工具,如圈复杂度检查) / 动态测试
(3)根据执行阶段–单元测试(模块内部-开发)/集成测试(模块交互-开发/测试) /系统测试 (测试)/ 验收测试(用户)
(4)根据目的-- 功能测试/性能测试/兼容性测试/安装测试 等
(5)更具测试执行结果校验方式–手动测试/自动测试
测试权衡要素—测试效率/测试覆盖率/测试框架引入
1、测试效率问题
由于时间和成本的约束,软件测试最关键的问题:在所有可能的测试用例中,哪个子集最有可能发现最多的错误。
从测试发现成本上看,开发人员的测试效率是最高的,如果把review也作为测试的一部分,那么发现问题概率就更高了。
2、测试覆盖率
很多公司都对测试覆盖率有标准(如语句测试 80%等),也会对测试问题发现阶段做约束(如 研发自测问题/测试问题/客户问题你 7:2:1等 )。我们应该意识到,单纯也把测试覆盖率作为质量指标没有意义,应该把覆盖率作为一种发现未测试的代码手段。分析未覆盖部分,反推测试设计是否做好,有没有测试重点缺失,特别时未覆盖的代码出现问题时,要反思最初评估是否正确,是否需要补充。覆盖率高的测试 设计不一定好,反过来 覆盖率低 的 测试 很难向他人证明 你的测试设计效率和代码质量, 只能从滞后的问题分布结果来看。
3、测试框架引入
不要自己造轮子,业界有很多常用的测试框架,如测试C语言平台cunit、java平台junit等。这些测试框架能能方便的提供一些 测试用例通用的行为控制需求,如:(1)提供测试suit(分类)管理和执行的能力;(2)提供用例手动选择执行和自动选择执行;(3)提供大量方便的测试assert(等于/不能与/返回值校验),用于指定结果;(4)提供测试结果报告输出 ;
用例设计编码原则—代码质量/划分粒度/执行速度/执行独立性/自校验/健壮性
0、用例代码质量和开发代码一致:测试代码如果没有做好质量控制,随着用例添加逐渐增多,用例本身 可读性、用例设计分层选择,性能 逐步出现问题,用例本身也会引入维护工作量,当用例本身 添加复杂、执行效率低、容易引起随机失败等问题出现,用例就会变为代码债务,需要加倍奉还。
1、测试粒度划分要小,用例代码控制在50行内:测试应该分类(分suit),针对每一个场景 规格点 进行单独测试。测试力度尽可能独立到一个规格或者特性。不要大包大揽的测试。测试的代码应该控制在50行以内,通过对测试公共行为进行封装,用例里面应该一眼能够看到 它测试的功能点。
2、测试执行要快:单个测试用例(除非特殊压测的用例以外),尽量低于1min,如果一个用例执行超过5min,大家就不愿意执行。
3、测试用例独立 相互无干扰:测试要可以随机重复执行,每次结果应该时一致的,不能A用例依赖B用例,或者 A执行后 B用例结果发生变化。
4、测试用例尽可能自动化:不要依赖人通过打印判断,或者 查询状态判断用例结果,用例应该尽可能自动化 自确认。即使多花10倍时间设计和编写一个用例,能给你节省数百倍,数千倍的手动执行确认时间。
5、测试用例要足够健壮:常见引入健壮性问题,对外部模块或者环境有太多依赖(其他模块出现问题,是否导致大部分自测用例不过?即使你本身业务正常。必须依赖);对配置有过多依赖,产品形态A只能执行一部分用例,产品版本B不能执行某些用例,都是设计用例阶段兼容性设计不足引入。过多无效/冗余 的断言,一个规格的测试用例应该集中在规格的测试点上,不要随意在一些不相关的动作 如 初始化等行为上添加断言,如果你认为这个动作需要测试,应该在它的单独用例里面添加判断。
三、测试用例设计 之 白盒/黑盒 手段
黑盒测试
(1)等价类划分—典型值
把全部输入的数据合理划分为若干等价类,在每一个等价类种取一个数据作为测试输入条件,以少量有代表性的测试数据取得比较好的测试结果。举个例子:测试产品输入分辨率,选择一个FHD以下,选一个FHD,选一个4K,选一个8K进行测试。
优点:通过测试设计方法,适用各种类型,以较少用例规模覆盖测试规格;缺点:没有组合测试;
(2)边界值分析—边界及异常边界
等价类的补充,**选择 正好等于左右边界,或者 刚好超过左右边界(异常值)**的数据作为测试数据。
(3)因果图分析—输入条件组合
等价类和边界值都没有考虑输入条件之间组合关系,因果图,就是运用图方法 对多个输入之间组合以及输入、输出之间 因果关系分析,生成 判定表,适用与检查各种输入组合情况。
基本流程:分析输入/输出,找出相互关系,明确约束和条件(剔除不可能组合),转化判定表按表项目测试。
(4)错误猜测—经验与直觉推测异常场景
基于经验和直觉推测程序中所有可能存在的各种错误,针对性的进行测试。如 接口异常输入(入参异常,文件异常,无效路径,缓冲溢出);系统状态异常(内存耗尽,cpu调度性能不足 调度超时)
白盒测试
语句 / 判定 / 条件 / 判断条件 / 多重条件 / 路径 覆盖
以下图为例子:
四、常见测试用例划分
1、功能测试-单元测试/模块测试/集成测试
主要针对基本的功能特性,如果一个小的特性在模块内部测试可以叫单元测试。你负责的模块进行单独功能测试(外部模块可以自己打桩构造),尽可能屏蔽外部模块影响,叫模块自测。集成测试就是把和你相关的模块串联起来到一个正常的工作环境中测试,关注相关模块交互行为和结果是否符合预期。
2、性能测试-接口耗时/cpu内存等资源占用/编译镜像size
3、异常测试-接口异常参数/模糊测试/异常流程测试(如ctrl+c后资源回收)
4、压力测试-切换流程压测/高频接口压测/并发行为压测/最大负载场景
5、典型场景-重点场景/基础场景/最大功能叠加场景
6、debug手段测试-调试命令/proc打印/报错和info信息
五、项目测试经验总结
1、开发人员测试效率思考—开发人员该如何测试?有哪些优势/劣势
一、开发人员员进行测试优势:
(1)对规格的理解更深刻,能明确每个测试场景效果/边界/约束
(2)对方案实现细节更熟悉,能有针对性的做覆盖测试,知道哪些规格及实现是 继承/新增/变化,有重点的测试,知道哪些规格之间有耦合的需要组合测试,哪些需要压力测试,设计效率更高;
(3)开发过程本身测试和开发是相辅相成的,开发人员必须写用例,用测试驱动开发,有一套好的开发测试能快速回归,帮助 开发过程 迅速 识别问题,帮助定位,澄清规格交付完整性。
(4)最核心的一点,开发人员在 设计模块 的 时候,本身 测试设计(模块如何更高效的测试) 和 维护设计(如何更快速定位维问题)就是 模块设计的一部分。开发人员的测试和维护设计做好,可以非常顺畅和快速的搞自动化测试,支持迭代开发和重构。
(5)源于上一点,开发人员在做模块设计时候非常灵活,可以通过设计做很好的测试规划和测试方案。
常见 如: 模块隔离设计 开发的时候经常会遇到 依赖模块没有准备好的情况,可以通过 测试桩 替代外部模块 进行独立的测试。测试平台迁移 如果外部依赖 封装与隔离做得足够好(包括 外部模块 和 系统接口),可以把 自己 的 模块代码 迁移到其他平台测试,举个例子 把 本来在arm linux环境的代码,直接编程好放在服务器上运行,可以极大提升测试效率 和 剥离对硬件环境的依赖。测试手段输出 可以把软件内部状态 输出到proc做自动化校验,合理的报错做自动化分析,以及研发人员的角度 有许多内部调试手段,如 嵌入式开发硬件的状态 上报测试。
二、研发测试的劣势:
开发人员测试 最容易忽视的点,(1)和外部模块交互部分往往是薄弱点,大家都关注自己的一亩三分地。(2)一些概率性问题测试往往不够,比如一些并发问题,往往 系统高负载状态下 压测 更容易暴露,但是模块自测常见 都是针对某个特性规格进行,缺少外部干扰和负载压力。(3)低优先级或者低价值的规格常常被 放低测试优先级。(4)依赖整机环境 或者 较为复杂的外部环境搭建时,开发者不愿投入太多工作量,容易选择性放弃。
2、测试观念与团队执行思考—关于团队的测试能力提升 和 开发测试氛围培养
一个开发团队,涉及的测试工作也是非常多并且极其重要的。很多团队很容易出现 重开发 轻测试 问题。如果测试用例投入不够,反过来 开发的问题 不能及时发现,后续解决成本直线上升,反过来影响开发计划。
常见测试工作如:
需求阶段 测试策略指定,
设计阶段 功能代码的可测试设计 / 功能代码的可维护设计 / 测试框架选型 / 测试依赖组件设计 / 测试自动化手段设计 / 测试用例表单设计
开发阶段 测试框架搭建 / 用例组件开发 / 测试用例编写/ 用例自动化整改
开发测试阶段-内部版本测试 测试构建以及执行效率提升 / 测试用例的周期执行工作 / 用例维护问题解决 / 问题用例补充和集成 / 测试覆盖率和测试问题分析