前端自动化测试(一)

最近公司项目在升级 react 技术栈,因为改动巨大,尤其是在路由改造和渲染方面。且我司项目庞大,路由众多,而我司主要测试靠人肉 e2e 测试,并没有做规范的高效率的自动化测试。所以此次升级回归测试范围很广,且风险很大。为了以后能够应对这种复杂的情况,故而研究一下前端自动化测试。

写着写着发现这个博客议题忒大,我们还是一点一点的写吧,第一篇我们先来学习一些概念,有一个理论基础,下一期再根据现在我司项目写一个自动化测试工具,来补充一下我们自动化测试的缺漏,并解决一下我们技术栈升级导致人肉回归测试不能全覆盖的问题。自动化测试是一个长期积累的过程,先迈出第一步吧。

ATDD & BDD & TDD

说到自动化测试,先讲一下几个开发模式。

ATDD Acceptance Test Driven Development(验收测试驱动开发)

在业务层次,在需求分析时就确定需求(如用户故事)的验收标准,即验收测试驱动开发(Acceptance Test Driven Development,ATDD)。

TDD Test Driven Development (测试驱动开发)

TDD 是一个开发测试代码和业务代码的工作流程,基于这个流程你可以写出具有极高测试覆盖率(通常接近 90%)的代码。TDD 还可以减少测试中发现比较难以定位的 BUG 的可能性。在代码层次,在编码之前写测试脚本,可以称为单元测试驱动开发(Unit Test Driven Development,UTDD)。在目前比较流行的敏捷开发模式(如极限编程、Scrum 方法等)中,推崇“测试驱动开发(Test Driven Development,TDD)”——测试在先、编码在后的开发实践。TDD 有别于以往的“先编码、后测试”的开发过程,而是在编程之前,先写测试脚本或设计测试用例。TDD 在敏捷开发模式中被称之为“测试优先的编程(test-first programming)”,而在 IBM Rational 统一过程(Rational Unified Process,RUP)中被称为“测试优先的设计(test-first design)”。所有这些,都在强调“测试先行”,使得开发人员对所做的设计或所写的代码有足够的信心,同时也有勇气进行设计或代码的快速重构,有利于快速迭代、持续交付。重构的前提就是测试就绪(testing is ready),在这样的前提下,重构的风险就很低,否则就有比较高的风险。

BDD Behavior Driven Development (行为驱动开发)

BDD 将 TDD 的一般技术和原理与领域驱动设计(DDD)的想法相结合。行为驱动开发是一种敏捷软件开发的技术,它鼓励软件项目中的开发者、QA 和非技术人员或商业参与者之间的协作。

行为驱动的开发人员使用他们的母语与领域驱动设计的语言相结合来描述他们的代码的目的和好处。

使用 BDD 的团队应该能够以用户故事的形式提供大量的“功能文档”,并增加可执行场景或示例。 BDD 通常有助于领域专家理解实现而不是暴露代码级别测试。它通常以 GWT 格式定义:GIVEN WHEN&THEN。

现状

ATDD 与 BDD 在某种意义上是一样的,都是站在用户的视角写的 Example,其实大部分小公司都是上边这两种,而测试只是做一些人肉的端对端测试,人肉测试,比较黑盒,不知道内部逻辑,并不能特别完整和数据比较极端的情况只关注整体业务逻辑是否是产品经理或所需要,且对于一些大项目技术栈升级或底层服务重构等的回归测试,不太好覆盖率百分之百的测试。当然了,单元测试也有它的问题,比如 ut 覆盖率,ut 本身错误,开发周期变长等。所以,对于前端来说,我们应该 BDD 和 TDD 相结合,不仅对代码逻辑进行检查测试,也对用户视觉业务逻辑进行检查测试,既要有 UT 测试,也要有测试同学人肉测试,互相查缺补漏,才能够产出稳定,bug 少,功能完全符合需求的从产品。对于,项目庞大,团队较大的公司,都应该要考虑,项目的稳定性,要放缓开发新需求的脚步,应该更加保证工程质量和产品稳定性。毕竟客户才是上帝。

为什么需要自动化测试

项目经过不断的开发,最终肯定会趋于稳定,在适当的时机下引入自动化测试能及早发现问题,保证产品的质量。

  • 自动化的收益 = 迭代次数 * 全手动执行成本 - 首次自动化成本 - 维护次数 - 维护成本

测试方法

黑盒测试

黑盒测试一般也被称为功能测试,黑盒测试要求测试人员将程序看作一个整体,不考虑其内部结构和特性,只是按照期望验证程序是否能正常工作。黑盒测试更接近用户使用的真实场景,因为对于用户来说,程序的内部是不可见的。

白盒测试

白盒测试是基于代码本身的测试,一般指对代码逻辑结构的测试。白盒测试是在了解代码结构的前提下进行的测试,目的是遍历尽可能多的可执行路径,得出测试数据。白盒测试方法比较多,主要是逻辑覆盖,即检查代码的每一行、每一次判断结果。

自动化测试分类

  1. 单元测试 (Unit Testing)
    单元测试是指对程序中最小可测试单元进行的测试,一般而言是指对函数进行的测试。单元测试混合了编程和测试,由于是对代码内部逻辑进行测试,因此更多的使用白盒的测试方式。单元测试能强迫开发者写出更可测试的代码,一般而言这样的代码可读性也会高很多,同时良好的单元测试可以作为被测代码的文档使用。偏向 TDD。

    函数可测性:可测试性高的函数一般而言是纯函数,即输入输出可预测的函数。即在函数内部不修改传入参数,不执行 API 请求或者 IO 请求,不调用其他非纯函数如 Math.random()等

    单元测试最大的特点是测试对象的细颗粒度性,即被测对象独立性高、复杂度低。

  2. 集成测试 (Integration Testing)
    集成测试是指在单元测试的基础上,将已测试过的单元测试函数进行组合集成暴露出的高层函数或类的封装,对这些函数或类进行的测试。
    集成测试最大的难点就是颗粒度较大,逻辑更加复杂,外部因素更多,无法保证测试的可控和独立性。解决方式是使用测试桩(测试替身),即将调用的子函数或模块替换掉,即可以隐藏子模块的细节并且可以控制子模块的行为以达到预期的测试。(这里的前提是子模块已经经过完整的单元测试进行覆盖,因此可以假定为子模块状态可知。)

  3. 端到端测试 (E2E Testing EndToEnd)
    端到端测试是最顶层的测试,即完全作为一个用户一样将程序作为一个完全的黑盒,打开应用程序模拟输入,检查功能以及界面是否正确。偏向 BDD。

  4. 持续集成测试
    持续集成就是通常所谓的 CI(Continuous integration),持续不断的自动化测试新加入代码后的项目。它并不属于单元测试,而是另外的范畴,不过通过使用 CI 服务可以很容易的在 Github 上测试项目,而这也就是持续集成的意义。

前端单元测试

前端单元测试和后端单元测试最大的区别在于,前端单元测试无法避免的会存在兼容性问题,如调用浏览器兼容性 API,以及对 BOM(浏览器对象模型)API 的调用,因此前端单元测试需要运行在(伪)浏览器环境下。
但是我搜了搜前端的单元测试框架,妈耶,不要太多,眼花缭乱,不知道该用啥。

首先我们要先分分类,看看都有什么类型的框架。

经搜索,了解到就运行环境大致分如下几类:模拟 dom、无头浏览器、真实浏览器

  1. 基于 JSDOM
    • 优点:快,执行速度最快,因为不需要浏览器启动
    • 缺点:无法测试如 seesion 或 cookie 等相关操作,并且由于不是真实浏览器环境因此无法保证一些如 Dom 相关和 BOM 相关的操作的正确性,并且 JSDOM 未实现 localStorage,如果需要进行覆盖,只能使用第三方库如 node-localStorage (这个库本身对与执行环境的判断有一些问题)进行模拟。
  2. 基于 PhantomJS、Head Less Chrome 等无头浏览器
    • 优点: 相对较快,并且具有真实的 DOM 环境
    • 缺点: 同样不在真实浏览器中运行,难以调试,并且项目 issue 非常多,puppeteer 发布后作者宣布不再维护
  3. 使用 Karma 或 puppeteer 等工具,调用真实的浏览器环境进行测试
    • 优点:配置简单,能在真实的浏览器中运行测试,并且 karma 能将测试代码在多个浏览器中运行,同时方便调试
    • 缺点: 唯一的缺点就是相对前两者运行稍慢,但是在单元测试可接受范围内

前端单元测试工具

然后我们再搜搜都有啥工具和框架

  1. 测试管理工具

    • karma – Google Angular 团队开发的测试运行平台,配置简单灵活,能够很方便将测试在多个真实浏览器中运行。它使用 Nodejs 构建,因此跨平台,还支持 PhantomJS 浏览器,还支持多种框架,包括以下介绍的 Jasmine、Qunit 和 Mocha。一次可以在多个浏览器及设备中进行测试,并控制浏览器行为和测试报告。虽然它不支持 Nodejs 的测试,不过没什么影响,因为 Nodejs 并不依赖于浏览器。
    • Buster,其作者之一就是 Christian Johansen。和 Karma 很像,也使用 Nodejs 编写跨平台并且支持 PhantomJS,一次测试所有客户端。更重要的是支持 Nodejs 的测试,同样支持各种主流测试框架。不过目前还在 Beta 测试中,很多 bug 而且不能很好的兼容 Windows 系统。它的目标还包括整合 Browser Stack。
  2. 测试框架

    • mocha – Tj 大神开发的很优秀的测试框架,有完善的生态系统,简单的测试组织方式,不对断言库和工具做任何限制,非常灵活。
    • jasmine – 和 Mocha 语法非常相似,最大的差别是提供了自建的断言和 Spy 和 Stub
    • jest – facebook 出品的大而全的测试框架,React 官方推荐的单元测试框架,配置简单运行速度快。(备注:无法和 Karma 进行集成)
    • Enzyme 是 Airbnb 公司提供的 React 测试工具,提供了 Shallow Rendering(浅渲染) | Full Rendering (全渲染)| Static Rendering (静态渲染)几种方式来渲染方式来测试 React 组件,一般常用浅渲染的方式进行测试。
    • AVA – 和上面的测试框架最大的区别在于多线程,运行速度更快。
    • 其他 – 还有一些其他的前端测试框架,但是相似度比较高,无非是对断言和测试桩等工具的集成度不同,如果考虑稳定以及成熟度建议选择 Mocha,对测试运行速度有非常高的要求可以考虑 jest 和 AVA
  3. 测试辅助工具

    • 断言库 – Chai 如果单元测试不跑在真实的浏览器环境中,可以简单使用 node 的 assert,但是建议使用 Chai 作为断言库(提供了 TDD 和 BDD 风格多种断言方式,并且生态系统繁荣)。
    • 测试桩(又称为测试替身) – Sinon、testDouble 等工具提供了如测试桩、拦截模拟请求、”时间旅行“等功能,主要用于解决”函数不纯”(比如测试回调是否被正确调用,XHR 是否正确发起请求,时间延迟后函数行为是否正确)的测试问题。
  4. 测试覆盖率工具

    • karma Karma-coverage
    • istanbul istanbul 的基础实现,提供了命令行等工具,但是无法解决代码编译打点的问题
    • istanbul-instrumenter-loader istanbul 的 Webpack 插件,能解决代码编译打点和测试报告输出的问题

前端单元测试选型

在框架选型的时候考虑到以下条件或问题:

  • 测试需要在真实浏览器中运行
  • 测试执行需要足够迅速
  • 被测代码可能是 es6 React Typescript,因此使用需要解决编译和打点的问题
  • 方便持续集成

咳咳,我还没完全掌握,还选不太出来,但是对于单元测试的需求是明确的,其实有点想用 jest,因为我司是 React 项目,但是呢我看好多人都用 karma,配合 mocha,chai 什么的。

我已经快不行了,翻阅了几十篇博客和文章,都没有看到一篇相对全面和有条理的文章,众说纷纭,可见大家对于前端自动化测试方面的关注度仍然不够多,不是只有后端才应该自动化测试,前端也需要,而且方案已经相对成熟,为了前端的稳定性,整!

自动化端到端测试(E2E Testing)

e2e 测试(不管是人肉的也好,自动化的也好)e2e 测试在整个系统测试的贯通性覆盖率上来说是最大的,它可以覆盖从地基到顶端的这一长串的范围。所以如果说 UT 是用来保证保证成品各个层级可靠性的话,那 e2e 就是用来验证这种可靠性的,并且它的作用范围运不止此。

说到端到端测试,首先要明确它需要解决的一些问题

  1. 环境问题

    即如何保证每次执行测试前的环境是“干净的”,比如需要检查列表为空的表现,如果上一次测试新增了列表,则后一次测试将无法得到列表为空的状态。

    最简单的解决方式是在所有测试执行前或测试执行后调用外部脚本清除数据库等,或者可以通过拦截请求并自定义响应的方式来解决(这样会导致测试复杂度变高,并且不够”真实“)。

  2. 元素查找

    如果代码经常变动,组件结构经常变化,如果根据 DOM 结构来查找操作元素,那么你将陷入维护选择器的地狱中。最佳实践是使用 test-id 的方式,但是这种方式需要开发人员和测试人员配合,在可操作元素上定义语义化的 test-id。

  3. 操作等待

    诸如异步网络请求导致界面变化,或界面动画等,将使得获取操作元素的时机未知。解决方案持续等待直到监听的请求完成,期望的元素成功获取到。

  4. 使用操作而不是断言

    应该更多的依赖操作,而不是依赖断言。例如如果某个操作依赖元素 A 存在,你不需要”判断元素 A 在页面中是否存在”,而应该去”直接获取元素 A,并操作”,因为如果元素 A 不存在,那么肯定将获取不到,断言后的操作将没有意义,因此可以直接使用操作取代断言等待功能。

Selenium & PhantomJS

自动化 e2e 测试,不得不说到 Selenium 和 PhantomJS。

Selenium 是一个用于 Web 应用程序测试的工具。Selenium 测试直接运行在浏览器中,就像真正的用户在操作一样。支持的浏览器包括 IE(7, 8, 9, 10, 11),Mozilla Firefox,Safari,Google Chrome,Opera 等。selenium 是一套完整的 web 应用程序测试系统,包含了测试的录制(selenium IDE),编写及运行(Selenium Remote Control)和测试的并行处理(Selenium Grid)。
Selenium 的核心 Selenium Core 基于 JsUnit,完全由 JavaScript 编写,因此可以用于任何支持 JavaScript 的浏览器上。Selenium 可以模拟真实浏览器,自动化测试工具,支持多种浏览器,爬虫中主要用来解决 JavaScript 渲染问题。可以使用 Selenium 与其他测试框架(如 jest)配合使用,效果很不错。

而 PhantomJS 使用无界面的 WebKit 浏览器,是一个基于 WebKit 的服务端 JavaScript API,支持 Web 而不需要浏览器支持,其快速、原生支持各种 Web 标准:Dom 处理,CSS 选择器,JSON 等等。PhantomJS 可以用用于页面自动化、网络监测、网页截屏,以及无界面测试。

其他工具

  1. CasperJS 只能是无界面浏览器测试。
  2. Nightwatch 是基于 Selenium 的一种更简洁的测试方案。
  3. TestCafe 支持常见浏览器,支持 ES6/ES7 和 TS,安装也方便。
  4. Cypress 开箱即用,文档比较清晰美观,语法用起来比较舒服,最重要的一点是测试跑在 Chrome 的标签页里,和平时开发没什么区别。Cypress 并没有使用 Selenium / Webdriver。

重要性

先说说 Regression Test 即回归测试,当有新功能上线后,我们需要对产品老的功能进行回归测试,以确保新代码的加入没有引入新的 bug。通常一次迭代中,QA 会花费大约 20~30%的时间进行回归测试,可见回归测试的重要性,但是很多情况下,由于项目时间紧迫,或者紧急发布等情况,被压缩和牺牲的往往是回归测试,而 e2e AT 正好可以覆盖一部分的回归测试,如果你的 AT case 覆盖率越高,则回归测试的覆盖率也越高,出品也就越稳定,如果 AT 能覆盖绝大部分的回归测试,而 AT 的执行效率又是人肉执行的数倍,那 QA 的工作量就被大大的降低。

何时触发

当新的代码合并到主线并部署到测试环境后,进入 QA 人肉测试环节前,是触发 自动化 e2e 测试 的最佳时机。bug 是越早发现越好,自动化 e2e 测试 与 jenkins 等 CI 工具可以很好的整合,也不依赖于什么特殊插件,跑完测试 后自动生成 report,若有失败则发送邮箱第一时间暴露问题。

总结

单元测试 和 端到端测试 的存在都是很有意义的。
unit 测试是程序员写好自己的逻辑后可以很容易的测试自己的逻辑返回的是不是都正确。
e2e 代码是测试所有的需求是不是都可以正确的完成,而且最终要的是在代码重构,js 改动很多之后,需要对需求进行测试的时候测试代码是不需要改变的,你也不用担心在重构后不能达到客户的需求。

本章先总结调研整理一些文档,下一篇我们进行一些技术选型,动手做一些单元测试,再下一篇,动手做一些 e2e 测试。

引用

https://juejin.im/entry/5b286a126fb9a00e45113435

https://juejin.im/entry/5b286a126fb9a00e45113435

https://zhuanlan.zhihu.com/p/32666685

https://segmentfault.com/a/1190000015724775?utm_source=sf-related

×

纯属好玩

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

文章目录
  1. 1. ATDD & BDD & TDD
    1. 1.1. ATDD Acceptance Test Driven Development(验收测试驱动开发)
    2. 1.2. TDD Test Driven Development (测试驱动开发)
    3. 1.3. BDD Behavior Driven Development (行为驱动开发)
    4. 1.4. 现状
  2. 2. 为什么需要自动化测试
  3. 3. 测试方法
    1. 3.1. 黑盒测试
    2. 3.2. 白盒测试
  4. 4. 自动化测试分类
  5. 5. 前端单元测试
  6. 6. 前端单元测试工具
  7. 7. 前端单元测试选型
  8. 8. 自动化端到端测试(E2E Testing)
    1. 8.1. 说到端到端测试,首先要明确它需要解决的一些问题
    2. 8.2. Selenium & PhantomJS
    3. 8.3. 其他工具
    4. 8.4. 重要性
    5. 8.5. 何时触发
  9. 9. 总结
  10. 10. 引用
,