《软件测试52讲》-谈谈测试

Posted by 瞿广 on Thursday, January 31, 2019

TOC

简单聊下我所了解的测试,测试基础知识、GUI 自动化测试、API 自动化测试、代码级测试、性能测试、测试数据准备、测试基础架构、测试新技术,测试覆盖率、软件缺陷报告、测试计划

单元测试

关于什么是单元测试,以及重要性就不再赘述了。

如何做好单元测试?

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

驱动代码,桩代码和 Mock 代码,是单元测试中最常出现的三个名词。驱动代码是用来调用被测函数的,而桩代码和 Mock 代码是用来代替被测函数调用的真实代码的。

驱动代码(Driver)指调用被测函数的代码,在单元测试过程中,驱动模块通常包括调用被测函数前的数据准备、调用被测函数以及验证相关结果三个步骤。驱动代码的结构,通常由单元测试的框架决定。

桩代码(Stub)是用来代替真实代码的临时代码。 比如,某个函数 A 的内部实现中调用了一个尚未实现的函数 B,为了对函数 A 的逻辑进行测试,那么就需要模拟一个函数 B,这个模拟的函数 B 的实现就是所谓的桩代码。 Mock 代码和桩代码非常类似,都是用来代替真实代码的临时代码,起到隔离和补齐的作用。但是很多人,甚至是具有多年单元测试经验的开发工程师,也很难说清这二者的区别。

在我看来,Mock 代码和桩代码的本质区别是:测试期待结果的验证(Assert and Expectiation)。

对于 Mock 代码来说,我们的关注点是 Mock 方法有没有被调用,以什么样的参数被调用,被调用的次数,以及多个 Mock 函数的先后调用顺序。所以,在使用 Mock 代码的测试中,对于结果的验证(也就是 assert),通常出现在 Mock 函数中。

对于桩代码来说,我们的关注点是利用 Stub 来控制被测函数的执行路径,不会去关注 Stub 是否被调用以及怎么样被调用。所以,你在使用 Stub 的测试中,对于结果的验证(也就是 assert),通常出现在驱动代码中。

在这里,我只想让你理解两者的本质区别以确保你知识结构的完整性,如果你想深入比较,可以参考马丁·福勒(Martin Fowler)的著名文章《Mock 代码不是桩代码》(Mocks Aren’t Stubs)

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

  1. 并不是所有的代码都要进行单元测试,通常只有底层模块或者核心模块的测试中才会采用单元测试。

  2. 你需要确定单元测试框架的选型,这和开发语言直接相关。比如,Java 最常用的单元测试框架是 Junit 和 TestNG;C/C++ 最常用的单元测试框架是 CppTest 和 Parasoft C/C++test;框架选型完成后,你还需要对桩代码框架和 Mock 代码框架选型,选型的主要依据是开发所采用的具体技术栈。

  3. 通常,单元测试框架、桩代码 /Mock 代码的选型工作由开发架构师和测试架构师共同决定。

  4. 为了能够衡量单元测试的代码覆盖率,通常你还需要引入计算代码覆盖率的工具。不同的语言会有不同的代码覆盖率统计工具,比如 Java 的 JaCoCo,JavaScript 的 Istanbul。在后续的文章中,我还会详细为你介绍代码覆盖率的内容。

  5. 最后你需要把单元测试执行、代码覆盖率统计和持续集成流水线做集成,以确保每次代码递交,都会自动触发单元测试,并在单元测试执行过程中自动统计代码覆盖率,最后以“单元测试通过率”和“代码覆盖率”为标准来决定本次代码递交是否能够被接受。

现状

我待过一些中国的互联网公司,也问过一些创业公司,进行单测的不多。我也一直在想没有单测,但是整体的质量也还能“说的过去”的原因是什么。

首先没有单测的主要原因还是和中国互联网的现状有关,中国的互联网本质是商业公司,在中国激烈的竞争环境下,业务的快速发展导致需求的快速上线是一个常态。这也导致了无论是产品还是开发经理,都是以支撑业务为kpi,其次才是质量。所以单测是一件不能直接体现到kpi上的隐形需求,项目排期一般也没有单测的时间。

那整体质量还过的去的原因其实也是因为互联网对质量的容忍度,允许出现一些非严重的问题,需要测试人员或qa通过checklist、集成测试工具或方法的提升能发现核心问题就够了,甚至通过监控和用户反馈紧急召回就够了。从这个方面也能说明中国的功能测试短期内不会像google一样完全被代替掉,还是会存在,根本是研发底层对质量的要求没有变化。不过不可否认的是,测试的一个趋势是写以提高质量的代码为目标,或许研发测试完全一体化之后,测试来写单测也不是一件不可能的事

GUI测试

现状

对于测试来说,并没有接触到代码级测试。经历过的公司,有的即使做了,也是由开发自行做单元测试或者代码评审之类。其他的自动化技术,有做过gui和api的自动化测试。但是gui自动化测试呢,在产品更迭迅速的互联网公司,经常页面,产品逻辑有微小变化,大多数用例就要推倒重来,维护成本太高。

WEB基于 Selenium 搭建

移动测试 Appium

小程序自动化测试

API测试

基于 Postman 和 Newman 的 API 测试

集成 Postman 和 Newman 的方案,然后再结合 Jenkins 就可以很方便地实现 API 测试与 CI/CDl 流水线的集成。Newman 其实就是一个命令行工具,可以直接执行 Postman 导出的测试用例。 用 Postman 开发调试测试用例,完成后通过 Newman 执行,这个方案看似很完美。

但是在实际工程实践中,测试场景除了简单调用单个 API 以外,还存在连续调用多个 API 的情况。 此时,往往会涉及到多个 API 调用时的数据传递问题,即下一个 API 调用的参数可能是上一个 API 调用返回结果中的某个值。

另外,还会经常遇到的情况是,API 调用前需要先执行一些特定的操作,比如准备测试数据等。 因此,对于需要连续调用多个 API 并且有参数传递的情况,Postman+Newman 似乎就不再是理想的测试方案了。

基于代码的 API 测试

为了解决这个问题,于是就出现了基于代码的 API 测试框架。比较典型的是,基于 Java 的 OkHttP 和 Unirest、基于 Python 的 http.client 和 Requests、基于 NodeJS 的 Native 和 Request 等。

小型的互联网企业,往往会根据自己的业务需求,选用这些成熟的 API 测试框架。 但是,对于中大型的互联网企业,一般都会自己开发更适合自身业务上下文的 API 测试框架,比如 eBay,我们为了实现代码化的 API 测试,开发了自己的 HttpClient,后期为了使 API 测试的代码更简洁易懂,就基于 Rest-Assured 封装了全新的 API 测试框架。

引用 康美之心 淇水之情:

Rest-assured是一个非常适合,非常好用的API开源测试框架,我已经在我们项目里基于Spring-boot,Rest-Assured,Ccucumber开发了一个标准通用的微服务API自动化测试框架,我们项目里的所有微服务API都可以基于框架快速高效的在各个测试环境无缝切换进行自动化测试,并且完全集成到了公司的CICD Jenkins平台,以前从开发到单元测试,FVT测试,UAT测试,回归测试到MTP需要3天左右时间的Size的Story,现在相同工作量Size的Story只需不到一天时间就可以全部完成,期间除了产品代码开发和少部分特殊数据的准备,部分新增用例的开发外,全部都是在Jenkins上自动完成。

这种根据公司业务上下文开发实现的 API 测试框架,在使用上有很多优点,而且灵活性也很好,主要体现在以下几个方面:

  • 可以灵活支持多个 API 的顺序调用,方便数据在多个 API 之间传递,即上一个 API 调用返回结果中的某个字段值可以作为后续 API 调用的输入参数;
  • 方便在 API 调用之前或者之后执行额外的任意操作,可以在调用前执行数据准备操作,可以在调用后执行现场清理工作等;
  • 可以很方便地支持数据驱动测试,这里的数据驱动测试概念和 GUI 测试中的数据驱动测试完全相同,也就是可以将测试数据和测试代码分离解耦;
  • 由于直接采用了代码实现,所以可以更灵活地处理测试验证的断言(Assert);
  • 原生支持命令行的测试执行方式,可以方便地和 CI/CD 工具做集成。

自动生成 API 测试代码是指,基于 Postman 的 Collection 生成基于代码的 API 测试用例。

性能测试

后端性能测试工具的原理是什么?

首先,后端性能测试工具会基于客户端与服务器端的通信协议,构建模拟业务操作的虚拟用户脚本

然后,开发完成了虚拟用户脚本之后,后端性能测试工具会以多线程或多进程的方式并发执行虚拟用户脚本,来模拟大量并发用户的同时访问,从而对服务器施加测试负载。

接着,在施加测试负载的整个过程中,后端性能测试工具除了需要监控和收集被测系统的各种性能数据以外,还需要监控被测系统各个服务器的各种软硬件资源

最后,测试执行完成后,后端性能测试工具会将系统监控器收集的所有信息汇总为完整测试报告

需要强调的是,测试结果分析器只是按需提供多种不同维度和表现形式的数据展现工作,而对数据的分析工作,还是要依赖于具有丰富经验的性能测试工程师。

后端性能测试场景设计是什么意思,具体会涉及哪些内容?

性能测试场景设计,是后端性能测试中的重要概念,也是压力控制器发起测试负载的依据。

性能测试场景设计,目的是要描述性能测试过程中所有与测试负载以及监控相关的内容。通常来讲,性能测试场景设计主要会涉及以下部分:

  • 并发用户数是多少?

  • 测试刚开始时,以什么样的速率来添加并发用户?比如,每秒增加 5 个并发用户。

  • 达到最大并发用户数后持续多长时间?

  • 测试结束时,以什么样的速率来减少并发用户?比如,每秒减少 5 个并发用户。

  • 需要包含哪些业务操作,各个业务操作的占比是多少?比如,10% 的用户在做登录操作,70% 的用户在做查询操作,其他 20% 的用户在做订单操作。

  • 一轮虚拟用户脚本执行结束后,需要等待多长时间开始下一次执行?

  • 同一虚拟用户脚本中,各个操作之间的等待时间是多少?

  • 需要监控哪些被测服务器的哪些指标?

  • 脚本出错时的处理方式是什么?比如,错误率达到 10% 时,自动停止该脚本。

  • 需要使用多少台压力产生器?

以上这些场景组合在一起,就构成了性能测试场景设计的主要内容。也就是说,性能测试场景会对测试负载组成、负载策略、资源监控范围定义、终止方式,以及负载产生规划作出定义,而其中的每一项还会包含更多的内容。具体请参见如图 1 所示的思维导图。

test-preference-scenario

业内主流的后端性能测试工具有哪些?

目前,业内有很多成熟的后端性能测试工具,比如传统的 LoadRunner、JMeter、NeoLoad 等。另外,现在还有很多云端部署的后端性能测试工具或平台,比如 CloudTest、Loadstorm、阿里的 PTS等。

另外,JMeter 是目前开源领域最主流的性能测试工具。JMeter 的功能非常灵活,能够支持 HTTP、FTP、数据库的性能测试,也能够充当 HTTP 代理来录制浏览器的 HTTP 请求,还可以根据 Apache 等 Web 服务器的日志文件回放 HTTP 流量,还可以通过扩展支持海量的并发。

所以互联网企业往往选用 JMeter 方案,而且通常会自己维护扩展版本。

关于测试计划

现状

测试计划总是被打乱,而且在前期需求未分析的情况下,测试进度估算的总是不准,很难把控 做好测试计划,很多时候被风险打乱,也就是不确定性打乱。如跨部门合作、技术攻关、预研项目不成熟等的引进等的不确定性 同时测试计划受开发进度,质量影响很大,可能之前估计一周搞完的结果质量太差,需要搞两周,那最后的发布日期都定下来,很可能就堆人,压缩测试周期了。

分类 功能
单元测试 确保类、模块功能正确
集成测试 确保组件间接口、交互和链路正确
组件测试 确保服务提供方和消费方都遵循契约规范
端到端测试 确保整个应用满足用户需求
探索测试 手工探索学习功能,改进自动化测试