基本理论篇

Q:什么是软件测试

软件测试的经典定义是:在规定的条件下对程序进行操作,以发现程序错误,衡量软件质量,并对其是否能满足设计要求进行评估的过程。

Q:软件测试分为几个阶段, 各阶段的测试策略和要求是什么

软件测试按阶段划分可以分为单元测试、集成测试、系统测试和<验收测试>(不一定有)几个阶段

单元测试测试策略:

  • 自顶向下的单元测试策略:比孤立单元测试的成本高很多,不是单元测试的一个好的选择。
  • 自底向上的单元测试策略:比较合理的单元测试策略,但测试周期较长。
  • 孤立单元测试策略:最好的单元测试策略。

集成测试的测试策略:

  • 大爆炸集成:适应于一个维护型项目或被测试系统较小

  • 自顶向下集成:适应于产品控制结构比较清晰和稳定;高层接口变化较小;底层接口未定义或经常可能被修改;产口控制组件具有较大的技术风险,需要尽早被验证;希望尽早能看到产品的系统功能行为。

  • 自底向上集成:适应于底层接口比较稳定;高层接口变化比较频繁;底层组件较早被完成。

  • 基于进度的集成:

    • 优点:具有较高的并行度;能够有效缩短项目的开发进度。
    • 缺点:桩和驱动工作量较大;有些接口测试不充分;有些测试重复和浪费。

系统测试的测试策略:

数据和数据库完整性测试;功能测试;用户界面测试;性能评测;负载测试;强度测试;容量测试;安全性和访问控制测试;故障转移和恢复测试;配置测试;安装测试;加密测试;可用性测试;版本验证测试;文档测试

Q:没有测试计划会怎么样

  1. 很难确切地知道具体的测试范围,以及应该采取的具体测试策略;
  2. 很难预估具体的工作量和所需要的测试工程师数量,同时还会造成各个测试工程师的分工不明确,引发某些测试工作被重复执行而有些测试则被遗漏的问题;
  3. 测试的整体进度完全不可控,甚至很难确切知道目前测试的完成情况,对于测试完成时间就更难预估准确的时间节点;
  4. 项目对潜在风险的抵抗能力很弱,很难应对需求的变更以及其他突发事件。

Q:测试计划工作的目的是什么?测试计划文档的内容应该包括什么?其中哪些是最重要的

软件测试计划是指导测试过程的纲领性文件。包含了产品概述、测试策略、测试方法、测试区域、测试配置、测试周期、测试资源、测试交流、风险分析等内容。借助软件测试计划,参与测试的项目成员,尤其是测试管理人员,可以明确测试任务和测试方法,保持测试实施过程的顺畅沟通,跟踪和控制测试进度,应对测试过程中的各种变更。

测试计划和测试详细规格、测试用例之间是战略和战术的关系,测试计划主要从宏观上规划测试活动的范围、方法和资源配置,而测试详细规格、测试用例是完成测试任务的具体战术。所以其中最重要的是测试策略测试方法(最好是能先评审)。

Q:缺陷(Bug)记录都包含了哪些内容?如何提交高质量的软件缺陷(Bug)记录

提交BUG时,描述应该包括以下的信息:

  • BUG产生对应的软件版本和模块
  • 开发的接口人员
  • BUG 的优先级
  • BUG 的严重程度
  • BUG 可能属于的模块,如果不能确认,可以用开发人员来判断
  • BUG 标题,需要清晰的描述现象
  • BUG 描述,需要尽量给出重现 BUG 的步骤
  • BUG 附件中能给出相关的日志,截图或者视频

高质量的 BUG 记录就是指很容易理解的 BUG 记录,所以对于描述的要求高,能提供的信息精准,很好的帮助开发人员定位。

Q:软件测试原则

  1. 所有的测试软件测试都应追溯到用户需求
    这是因为软件测试的目的是使用户完成预定的任务,并满足用户的需求,而软件测试的所揭示的缺陷和错误使软件达不到用户的目标,满足不了用户的需求。
  2. 应当将“尽早地和不断地进行软件测试”作为软件测试者的座右铭
    测试需求贯穿整个软件的生命周期,缺陷修复成本随着各个阶段的靠后而提升。从平时的醒目中已看出,需求阶段引入的bug不比设计阶段少,如何保证好需求的稳定有效已经至关重要。
  3. 完全测试是不可能地,测试需要终止
    即Zero Bug与Good Enough;本条给我们灌输的是一种测试执行通过的标准。显示任何测试通过不可能达到0bug。那我们就应该达到Good Enough。这条原则是一种权衡投入/产出比的原则:测试既不能不充分也能过,我们需要制定测试通过标准和测试内容,比如:遗留的bug数&严重程度,测试用例的执行率&通过率等来解决上面的问题。
  4. 软件测试无法显示软件潜在的缺陷
    进行测试时可以查找并报告发现的软件缺陷和错误,但是不能保证软件的缺陷和错误能全部找到,继续进一部测试可能还会找到一些,也就是说测试只能证明软件存在错误而不能证明软件没有错误。
  5. 充分注意测试中的集群现象
    即80-20原则;这条主要想告诉我们的就是缺陷的集群现象,发现缺陷越多的模块就需要投入更多的人力精力去测试。
  6. 程序员应避免检查自己的程序
    为了达到测试目的,应由客观、公正、严格的独立的测试部门或者独立的第三方测试机构进行测试。
  7. 尽量避免测试的随意性
    制定严格的测试计划,并把测试时间安排的尽量宽松,有组织、有计划、有步骤的开展测试活动。
  8. 回归测试的关联性
    回归测试的关联性一定要引起充分注意。修改一个错误而引起更多错误出现的现象并不少见。
  9. 关注程序不该做的事
    检查程序应该完成哪些功能,这只是测试工作的一半,测试工作的另一半是,检查程序完成了哪些不应该完成的功能。

个人篇

Q:测试人员该有的素质

保持怀疑
对产品的质量持有一颗敢于怀疑的心,质量不是开发人员说”我做完了而且也测过了”就可以保证的。直到你测完最后一轮,最后一个用例之前,你都应该对产品的质量持怀疑态度。这个态度是混口饭吃的最基本技能。

永不妥协
不要对产品质量妥协,哪怕开发口口声声说这个问题不好改,改不了,一改就要延期之类的话。妥协意味着你成功的把质量不好这口黑锅华丽的背在了自己的身上。

让用户满意
产品或项目成功的标志之一是能够让用户满意,很显然用户是不会对一个bug频出的系统/产品满意的。

从用户角度思考
- 从用户角度去思考,如果你是一个特定的用户(年龄,身份,职业)你应该会怎么使用这个产品
- 从场景的角度去思考,在哪些场景下会使用到这个产品

分清主次
要分清楚任务的优先级,优先级高的先做,依此类推。在没有分清优先级的情况下不要盲目的开始测试。

从不承诺100%的覆盖率
做不到也不可能做到。

倾听建议
别人的建议有些是金玉良言,有些则可以忽略不计。做测试的时候你不是一个人在战斗,多听听别的的有效建议是没有坏处的。

尽早开始
尽早开始重要的模块的测试工作。因为问题发现的越早解决的成本就越低。另外早点开始测试重要的模块或功能可以尽可能多的增加测试时间,拿时间换质量一般来说是效果的。这个建议的另一个说法就是想办法让重要的模块可以尽早的开始测试。

确定并管理风险
在做项目测试的时候,一个好的测试同学需要有发现项目质量上可能出现的风险的能力。另外当发现了项目风险的时候,我们还需要能够将风险管理起来,让风险可以被控制,可以被解决。

做市场调研
看看友商的产品做的怎么样,有什么好的地方,有什么不好地方。好的地方我们的产品可以学习,不好的地方我们可以预防和改进。这是站在产品人员的角度去看待自己的项目或产品,因为好的测试在某些时候需要具备好的产品人员的素质。

培养BA技能
BA就是业务分析师的意思,在某些项目里,这类同学被称为产品狗。这要求测试人员有分析需求的能力,哪些需求是真需求,哪些需求是伪需求。真需求就玩命的测,伪需求在时间允许的情况下尽量的测。这也是产品视角,这也是为什么有很多测试同学转去做产品的原因。

不要忘了异常情况
只测试正常的流程往往是不太够的,一些异常的情况我们也需要进行测试。另外不出意外的话异常情况的测试用例数量是要多于正常情况的。测试异常情况有助于我们发现bug,也有助于我们换个角度看待产品和项目的业务行为。

Be a Good Judge of Your Product
做那个对项目/产品最有发言权的人。学会交涉在保证项目质量的前提下我们要尽可能多的通过交涉和协商保障自己的利益。交涉意味着在某些情况下我们需要做出让步,退一步海阔天空,但前提是,退的这一步不影响项目或产品的质量。停止指责出问题的时候第一要务是先把问题解决掉,而不是指责相关责任人。

做一个好的观察者
观察项目,观察开发的流程,观察测试的流程,发现问题,提出问题,引导团队去解决问题。

Q:你有哪些优秀特质:(结合自身即可)

  • 有韧性
  • 有耐心
  • 做事有条理性
  • 喜欢挑战
  • 有信心做好每一件事情
  • 较强的沟通能力

能力篇

功能

自动化

Q:什么是自动化测试

自动化测试是,把人对软件的测试行为转化为由机器执行测试行为的一种实践。

自动化测试的本质是先写一段代码,然后去测试另一段代码,所以实现自动化测试用例本身属于开发工作,需要投入大量的时间和精力,并且已经开发完成的用例还必须随着被测对象的改变而不断更新,你还需要为此付出维护测试用例的成本。

Q:为什么需要自动化测试

一般情况下,回答自动化测试的优势即可。

优势

  1. 替代大量的手工机械重复性操作,把更多的时间花在更全面的用例设计和新功能的测试上;
  2. 大幅提升回归测试的效率,非常适合敏捷开发过程;
  3. 更好地利用无人值守时间,去更频繁地执行测试,特别适合在非工作时间执行测试,工作时间分析失败用例的工作模式;
  4. 高效实现某些手工测试无法完成或者代价巨大的测试类型,比如关键业务 7×24 小时持续运行的系统稳定性测试和高并发场景的压力测试等;
  5. 可以保证每次测试执行的操作以及验证的一致性和可重复性,避免人为的遗漏或疏忽。

但是我们也需要了解自动化测试的不足和劣势

  1. 自动化测试并不能取代手工测试,它只能替代手工测试中执行频率高、机械化的重复步骤。
  2. 自动测试远比手动测试脆弱,无法应对被测系统的变化,自动化测试维护成本高。按部就班地执行事先定义好的测试步骤并验证测试结果,对执行过程中出现的明显错误和意外事件,自动化测试没有任何处理能力。
  3. 自动化测试用例的开发工作量远大于单次的手工测试,所以只有当开发完成的测试用例的有效执行次数大于等于 5 次时,才能收回自动化测试的成本。
  4. 手工测试发现的缺陷数量通常比自动化测试要更多,并且自动化测试仅仅能发现回归测试范围的缺陷。
  5. 测试的效率很大程度上依赖自动化测试用例的设计以及实现质量,不稳定的自动化测试用例实现比没有自动化更糟糕。
  6. 实行自动化测试的初期,用例开发效率通常都很低,大量初期开发的用例通常会在整个自动化测试体系成熟,和测试工程师全面掌握测试工具后,需要重构。
  7. 业务测试专家和自动化测试专家通常是两批人,前者懂业务不懂自动化技术,后者懂自动化技术但不懂业务,只有二者紧密合作,才能高效开展自动化测试。
  8. 自动化测试开发人员必须具备一定的编程能力

Q:什么样的项目适合自动化测试

  1. 需求稳定,不会频繁变更
  2. 研发和维护周期长,需要频繁执行回归测试
  3. 需要在多种平台上重复运行相同测试的场景
  4. 某些测试项目通过手工测试无法实现,或者手工成本太高
  5. 被测软件的开发较为规范,能够保证系统的可测试性
  6. 测试人员已经具备一定的编程能力

单元测试

Q:什么是单元测试

对软件中的最小可测试单元在与程序其他部分相隔离的情况下进行检查和验证的工作,这里的最小可测试单元通常是指函数或者类。

单元测试通常由开发工程师完成,一般会伴随开发代码一起递交至代码库。单元测试属于最严格的软件测试手段,是最接近代码底层实现的验证手段,可以在软件开发的早期以最小的成本保证局部代码的质量。另外,单元测试都是以自动化的方式执行,所以在大量回归测试的场景下更能带来高收益。

Q:如何做好单元测试

  1. 首先必须弄清楚单元测试的对象是代码,以及代码的基本特征和产生错误的原因
  2. 然后你必须掌握单元测试的基本方法和主要技术手段,比如什么是驱动代码、桩代码和 Mock 代码等

代码的基本特征与产生错误的原因

  • 基本特征:代码对数据进行分类处理,包括一次条件判定,嵌套的条件判定或者循环执行
  • 错误原因:
    1. 分类遗漏
    2. 分类错误
    3. 分类时处理逻辑错误

单元测试用例详解

单元测试的用例是一个“输入数据”和“预计输出”的集合。了解即可

输入数据:

  1. 被测试函数/方法的输入参数;
  2. 被测试函数/方法内部需要读取的全局静态变量;
  3. 被测试函数/方法内部需要读取的成员变量;
  4. 函数/方法内部调用子函数/子方法获得的数据;
  5. 函数/方法内部调用子函数/子方法改写的数据;

预计输出:

  1. 被测试函数/方法的返回值;
  2. 被测试函数/方法的输出参数;
  3. 被测试函数/方法所改写的成员变量;
  4. 被测试函数/方法所改写的全局变量;
  5. 被测试函数/方法中进行的文件更新;
  6. 被测试函数/方法中进行的数据库更新;
  7. 被测试函数/方法中进行的消息队列更新;

代码覆盖率

代码覆盖是软件测试中的一种度量,描述程序中源代码被测试的比例和程度,所得比例称为代码覆盖率。

代码覆盖率的价值

统计代码覆盖率的根本目的是找出潜在的遗漏测试用例,并有针对性的进行补充,同时还可以识别出代码中那些由于需求变更等原因造成的不可达的废弃代码。

代码覆盖率最佳实践

了解即可!引用自我翻译的《Google - 代码覆盖率最佳实践

  • 代码覆盖率为开发工作流程带来了显而易见的收益
  • 是否仅通过代码覆盖就能减少缺陷是一个开放的研究问题
  • 高代码覆盖率并不能保证测试覆盖的高质量
  • 低代码覆盖率的确可以说明在每次部署时都不会通过自动化来完全测试产品的大部分场景
  • 没有一个可以普遍适用于所有产品的“理想的代码覆盖率”
  • 一般来说,很多产品的代码覆盖率都低于标准,我们应该以大幅提高全面的代码覆盖率为目标
  • 比覆盖行数百分比更重要的是,人们对未被覆盖的实际代码行数(和行为)的判断(分析测试的差距)
  • 仅仅因为你的产品代码覆盖率低,并不意味着你不能采取具体的、渐进的步骤来改进它
  • 确保覆盖经常变更的代码
  • 单元测试代码的覆盖率只是其中一部分
  • 我们应该限制不符合代码覆盖标准的部署

Q:驱动代码、MOCK代码、桩代码区别

驱动代码是用来调用被测函数的,而 桩代码Mock代码 是用来代替被测函数调用的真实代码的。

不同点

  1. 类实现的方式:stub有一个显式的类实现,而mock实现类通常是由mock工具包,比如easymock,jmock隐式实现
  2. 测试逻辑的可读性:mock代码与测试代码放在一起,从测试代码可以看出mock的代码逻辑;而stub则需要进入到具体的实现类中查看
  3. 可复用性:mock很少考虑复用,通常遵循 just enough 原则即可;而stub则比较方便复用
  4. 设计与使用:stub是state-based,关注的是输入和输出;mock是interaction-base,关注的是交互过程
  5. 期望:对mock来说,期望是非常重要的,Mock方法有没有被调用,以什么样的参数被调用,被调用的次数,以及多个 Mock 函数的先后调用顺序,需要验证和期望是否一致。而stub则不关注期望
  6. 结果的验证:mock代码通常包含结果的验证;而stub对于结果的验证通常出现在驱动代码中

实际项目中如何开展单元测试

  1. 通常只有底层模块或者核心模块的测试中才会采用单元测试。
  2. 单元测试框架的选型,Java - Junit 和 TestNG;C/C++ - CppTest 和 Parasoft C/C++test;需要对桩代码框架和 Mock 代码框架选型
  3. 引入计算代码覆盖率的工具。比如 Java 的 JaCoCo,JavaScript 的 Istanbul。
  4. 把单元测试执行、代码覆盖率统计和持续集成流水线做集成,以确保每次代码递交,都会自动触发单元测试,并在单元测试执行过程中自动统计代码覆盖率,最后以“单元测试通过率”和“代码覆盖率”为标准来决定本次代码递交是否能够被接受

单测推行难点

(了解即可)

  • 紧密耦合的代码难以隔离;
  • 隔离后编译链接运行困难;
  • 代码本身的可测试性较差,通常代码的可测试性和代码规模成反比(代码量越大,可测性越差);
  • 无法通过桩代码直接模拟系统底层函数的调用;
  • 代码覆盖率越往后越难提高。

性能

前端性能

后端性能

兼容性

安全