[TOC]
# 持续集成和前端自动化测试
持续集成是互联网软件开发上线流程中的核心一环,自动化测试是持续集成得以实现的核心步骤,缺乏了自动化测试,持续集成自然无从谈起。
在日常的开发中,前端错综复杂的变化引发的 bug 往往令开发者头疼,或多或少经历过 修完东墙西墙倒 的经历,此时前端自动化测试就显得非常重要。
前端的自动化测试无非也是编写测试用例,在持续集成时执行跑通全部测试用例。如果是一个短平快的小项目,引入前端自动化测试,编写测试用例,无疑只会增加开发成本,然而当项目扩大、迭代频繁、逻辑复杂、需求反复变更的情况下,回归测试的成本是巨额的,自动化测试的优势就能体现出来。
> 自动化测试的收益 = 迭代次数 \* 全手动执行成本 - 首次自动化成本 - 维护次数 \* 维护成本
尽早引入前端自动化测试不仅能够减少项目 bug 出现概率 (尤其是回归测试中的 bug),还能更好地进行代码组织,增强项目的可维护性,尤其对于工程质量较差的项目,收益是巨大的;如果将其应用于持续集成中,commit 触发自动执行测试脚本,还能大幅提升团队的开发效率。
# 自动化测试的必要性
好处很多,包括减少错误、提高效率等,尤其是前端项目越来越庞大且多人维护时,前端自动化测试就会显得尤其重要。
代价也有,毕竟需要额外的学习成本。但在你的项目中加入测试,也许没你想象的那么困难。
# [JavaScript 测试︰ 单元 vs 功能 vs 集成测试](http://wildflame.me/javascript-testing-unit-functional-integration/)
大多数应用程序都需要 单元测试 和 功能测试,而许多复杂的应用程序在此基础上,还需要 集成测试。
1. **单元测试** 测试单个函数或者类,提供输入,确保输出和预期的一样。单元测试的粒度要尽可能小,不要考虑其他类和模块的实现。用来确保每个组件正常工作 —— 测试组件的 API 。在面向对象的语言中,单元可以从单一方法到整个类。
2. **集成测试** 测试整个流程或者某组件能够按预期的运行,用来覆盖跨模块的过程。同时也要包括一些反面用例,用来确保不同组件互相合作 —— 测试组件的 API, UI, 或者边缘情况(比如数据库I/O,登陆等等)。
3. **功能测试** 站在产品的角度测试各个场景,通过操作浏览器或者网站,忽略内部实现细节和结构,确保和预期的行为一样。—— UI 界面功能测试
你应该把 单元,集成 和 功能测试 互相隔离开来,这样你就可以在开发时分别的运行它们。在持续的集成过程中,测试一般会出现在下面三个阶段。
1. 开发阶段,主要是程序员反馈。这时单元测试很有用。
2. 中间阶段,主要是能够在发现问题时立刻停下来。这时各种测试都很有用。
3. 生产环境,主要是运行功能测试套件中一个叫做「冒烟测试」的子集,确保部署的时候没有弄坏什么东西。
如果你问我该使用那个测试?**所有的**。
**在前端测试金字塔中,大部分测试都是单元测试。**
# BDD vs TDD
主流的测试类型,如何选择测试的策略。
## TDD (Test-Driven Development) 测试驱动开发
TDD 顾名思义,开发者根据需求先编写测试用例,再逐步开发,最终满足全部测试用例的需求。
TDD 的基本思路就是通过测试来推动整个开发的进行,但测试驱动开发并不只是单纯的测试工作,而是把需求分析,设计,质量控制量化的过程。
TDD 的重要目的不仅仅是测试软件,测试工作保证代码质量仅仅是其中一部分,而且是在开发过程中帮助客户和程序员去除模棱两可的需求。TDD 首先考虑使用需求(对象、功能、过程、接口等),主要是编写测试用例框架对功能的过程和接口进行设计,而测试框架可以持续进行验证。
刚开始的时候,只有测试用例,未进行功能开发,执行测试用例,满屏是红色的测试用例不通过提示,随着测试用例被满足变绿,最终全部变绿,功能开发完成,因此前端自动化测试也被叫做 Red-Green Development。
> TDD 先写测试再写代码,单位是模块,多用于 单元测试
> 重点在测试代码,属于 白盒测试
> 测试内容是模块,速度快,但是忽略模块间依赖,安全感低
>
> 流程
> 1. 编写测试用例
> 2. 运行测试,测试用例无法通过测试
> 3. 编写代码,时测试用例通过测试
> 4. 优化代码,完成开发
> 5. 重复上述步骤
>
> 优势
> 1. 长期减少回归 bug
> 2. 代码质量更好(组织,可维护性)
> 3. 测试覆盖率高
> 4. 错误测试代码不容易出现
## BDD (Behavior Driven Development) 行为驱动开发
测试用例模拟用户的操作行为,通常在完成业务代码开发之后,以用户的操作为指导编写测试代码。当测试用例跑通之后,就可以认为系统的整体流程已经流畅。
BDD 的模式适用于平时的业务代码开发,因为业务的需求有可能变更频繁,但操作流程有可能不会变化,当业务代码发生变化的时候,可以使用原来的测试用例继续跑代码,节省了开发时间。
BDD 先写代码再写测试,测试单位是功能,多用于集成测试
重点在测试 UI(DOM)功能,属于黑盒测试
测试内容是整套操作流程,速度慢,往往需要多个模块配合,安全感高
> TDD 开发模式更适用于开发,类似方法函数库,对于数据的处理,对于这种显示组件,更加推荐于 BDD 的开发方式,这样既有了测试,也不会增加过多的工作负担,
>
> 在平时的项目中,通常使用 TDD 和 BDD 相结合来进行测试,TDD 负责方法类、独立组件的测试。BDD 则负责整体业务模块的测试。
一般的 TDD 的开发流程为:
1. 编写测试 (一个会失败的 case)
2. 运行测试,并看到这个测试失败
3. 编写代码 (足够让测试通过的代码)
4. 运行测试,并看到测试通过
5. 重构
6. 运行测试,并看到测试通过
然后**如此循环**,而在前端开发中,很长一段时间,这个流程受限于开发环境,比如添加了一个新的 JavaScript 源文件,开发者需要在 HTML 中引入相应地文件,以及响应的测试文件,然后刷新页面 (有时候还需要清空浏览器缓存)。
在这个过程中,开发者真正关注的就是编写测试,运行测试,编写实现,重构等等,需要不断的重复这个过程。而不是关注如刷新页面,清空缓存,修改 HTML 对脚本的引用等武馆的工作。
参考:
* [前端自动化测试jest_萌萌哒的瑞萌萌的博客](https://blog.csdn.net/weixin_46232841/article/details/117528453)
* [TDD 与 BDD 仅仅是语言描述上的区别么? - 知乎](https://www.zhihu.com/question/20161970)
* [从Unit Test到TDD再到BDD](https://www.jianshu.com/p/07f5ea4761ad)
* [虚拟座谈会:代码测试比率、测试驱动开发及行为驱动开发](http://www.infoq.com/cn/articles/virtual-panel-tdd-bdd)
## 断言库 Chai
断言库(assertion library)是用来写断言的库。
维基百科的 [断言(程序)](https://zh.wikipedia.org/wiki/%E6%96%B7%E8%A8%80_(%E7%A8%8B%E5%BC%8F))一文是这么解释断言的:在[程序设计](https://zh.wikipedia.org/wiki/%E7%A8%8B%E5%BC%8F%E8%A8%AD%E8%A8%88)中,**断言**(**assertion**)是一种放在程序中的[一阶逻辑](https://zh.wikipedia.org/wiki/%E4%B8%80%E9%9A%8E%E9%82%8F%E8%BC%AF)(如一个结果为真或是假的逻辑判断式),目的是为了标示与验证程序开发者预期的结果-当程序运行到断言的位置时,对应的断言应该为真。若断言不为真时,程序会中止运行,并给出错误消息。
根据风格,断言库又区分为 TDD 风格 和 BDD 风格。[Chai](http://chaijs.com/) 便是其中一个著名的代表,它同时支持这两种风格。
# 前端测试金字塔
前端测试金字塔是一个前端测试套件应该如何构建的结构化表示。
理想的测试套件由单元测试,一些快照测试和一些端到端(e2e)测试组成。
![](https://box.kancloud.cn/06001c162f34e2a232bd29a58f17e901_321x242.png)
这是测试金字塔的改进版本,特定于测试前端应用程序。
# 前端测试框架
在大型项目或迭代频繁的项目中,单元测试还是很必要的,当前单元测试框架很多,功能各不相同。使用测试框架的好处是可以让我们写测试更方便,比如有测试结果报告,还有一些 helper function 来帮助我们更好的编写和组织测试代码,比如`expect(counter.number).to.be.equal(0)`就是测试框架提供的很容易理解的代码。
![热门的 JavaScript 自动化单元测试框架](https://box.kancloud.cn/d757cf9ad6183c08a10df8a754e394f5_643x418.png)
## Jest
https://jestjs.io/zh-Hans/
* facebook 靠山
* 基于 Jasmine 至今已经做了大量修改添加了很多特性
* 开箱即用配置少,API 简单
* 支持断言和仿真
* 支持快照(snapshot)测试
* 在隔离环境下测试
* 互动模式选择要测试的模块
* 优雅的测试覆盖率报告,基于 Istanbul
* 较新,社区不十分成熟
* 全局环境,比如 describe 不需要引入直接用
* 较多用于 React 项目(但广泛支持各种项目)
> [Why Do JavaScript Test Frameworks Use describe() and beforeEach()?](https://www.bignerdranch.com/blog/why-do-javascript-test-frameworks-use-describe-and-beforeeach/)
> [Testing JavaScript with Jest](https://flaviocopes.com/jest/#run-jest-with-vs-code)
> https://www.valentinog.com/blog/jest/
## Mocha
[Mocha](https://mochajs.org/) 是一个功能丰富的 JavaScript 测试框架,运行在 Node.js 和浏览器上,使得异步测试简单而有趣。Mocha 测试是串行运行的,允许灵活和准确的报告,同时将未捕获的异常映射到正确的测试用例。
默认会自动运行当前项目的 `test` 文件夹下的测试文件。
* 灵活(不包括断言和仿真,自己选对应工具)
流行断言库可选择:[chai](https://www.chaijs.com/api/assert/),[sinon](https://ssh://github.com/sinonjs/sinon)
* 社区成熟用的人多,测试各种东西社区都有示例
* 需要较多配置
* 可以使用快照测试,但依然需要额外配置
> [Unit testing Node.js applications using Mocha, Chai, and Sinon](https://blog.logrocket.com/unit-testing-node-js-applications-using-mocha-chai-and-sinon/)
## Jasmine
[Jasmine](https://jasmine.github.io/index.html) 是一个针对 JavaScript 的行为驱动开发的测试框架,不依赖于任何其他的 JavaScript 框架或者文档对象模型(DOM),最新版本改进了对 Node.js 的支持,同时还做了一些提升内部质量的工作。
* 开箱即用(支持断言和仿真)
* 只支持 BDD
* 全局环境
* 不依赖于任何其它的 JavaScript 框架
* 不需要 DOM
* 结构简单
* 可以运行在 Node.JS 或者 Html 中
* 基于行为驱动开发 Jasmine
## AVA
未来的测试运行器。
从 Mocha 切换到 AVA 让测试时间从 31 秒下降到 11 秒。测试并发执行强制你写原子测试,意味着测试不需要依赖全局状态或者其他测试的状态,这是一件非常好的事情。
[avajs/zh_CN/readme.md](https://github.com/avajs/ava-docs/blob/master/zh_CN/readme.md)
## Karma
[Karma](https://karma-runner.github.io/) 是一个基于 Node.js 的 JavaScript 测试执行过程管理工具(Test Runner)。由 Google 团队开发的一套前端测试运行框架。它不同于测试框架(例如 jasmine,mocha 等),该工具可用于测试所有主流 Web 浏览器,也可以集成到 CI(Continuous integration)工具,还可以和其他代码编辑器一起使用。
Karma 会监控配置文件中所指定的每一个文件,每当文件发生改变,它都会向测试服务器发送信号,来通知所有的浏览器再次运行测试代码。此时,浏览器会重新加载源文件,并执行测试代码。其结果会传递回服务器,并以某种形式显示给开发者。
访问浏览器执行结果,可通过以下的方式:
* 手工方式 - 通过浏览器,访问 URL 地址 - http://localhost:9876/
* 自动方式 - 让 karma 来启动对应的浏览器
主要完成以下工作:
1. Karma 启动一个 web 服务器,生成包含 js 源代码和 js 测试脚本的页面;
2. 运行浏览器加载页面,并显示测试的结果;
3. 如果开启检测,则当文件有修改时,执行继续执行以上过程。
## 其他
如果想要对前端产品进行测试,还需要另外一个工具:
* 测试浏览器 -- [Puppeteer](Puppeteer%E5%AD%A6%E4%B9%A0.md)
# 前端e2e测试
单元测试
·业务驱动开发 & 测试驱动开发
·黑盒测试和白盒测试
·测试覆盖率
·前端项目的单测集成
·Node项目的单测集成
e2e测试
·前端e2e测试
## 附录
http://www.daqianduan.com/1845.html
前端测试工具集锦 https://qaseven.github.io/2016/05/24/front-end-tools/
https://www.douban.com/note/509058712/
[前端自动化测试](https://www.baidu.com/s?wd=%E5%89%8D%E7%AB%AF%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95)
[如何进行前端自动化测试?](https://www.zhihu.com/question/29922082)
[聊聊前端开发的测试](https://zhuanlan.zhihu.com/p/26050231)
# 用 Headless Chrome 代替 Phantomjs。
1. 我爸是 Google ,那么就意味不会出现 Phantomjs 近 2k 问题没人维护的尴尬局面。 比 Phantomjs 有更快更好的性能。
2. 有人已经做过实验,同一任务,Headless Chrome 要比现 Phantomjs 更加快速的完成任务,且占用内存更少
3. chrome 对 ECMAScript 2017 (ES8) 支持,同样 headless 随着 chrome 更新,意味着我们也可以使用最新的 js 语法来编写的脚本,例如`async`,`await`等。
4. 完全真实的浏览器操作,chrome headless支持所有chrome特性。
5. 更加便利的调试,我们只需要在命令行中加入 `--remote-debugging-port=9222`,再打开浏览器输入 `localhost:9222` (ip为实际运行命令的ip地址)就能进入调试界面。
Google 最近放出了终极大招—— [Puppeteer 学习](Puppeteer%E5%AD%A6%E4%B9%A0.md)
***
# chrome 跨域调试
跨域设置
~~~
--disable-web-security
~~~
1. Chrome 桌面快捷方式=》鼠标右键=》属性-》目标后。
2. MyChrome -》高级-》启动参数
`Allow-Control-Allow-Origin:*` [跨域插件](https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi)
# 单元测试工具
[Mocha](https://mochajs.org/)
[k6](https://k6.io/)
单元测试工具 —— [karma](http://karma-runner.github.io/latest/index.html)(跑测试用例的容器)
[jasmine](https://jasmine.github.io/) —— 编写测试用例。
[macaca](https://github.com/alibaba/macaca) —— 多端自动化测试解决方案
# 参考
[测试网](http://www.51testing.com/html/96/category-catid-96.html)
[你需要了解的前端测试“金字塔”](http://web.jobbole.com/93120/)
[测试你的前端代码 – part1(介绍篇)](http://web.jobbole.com/91123/)
- 讲解 Markdown
- 示例
- SVN
- Git笔记
- github 相关
- DESIGNER'S GUIDE TO DPI
- JS 模块化
- CommonJS、AMD、CMD、UMD、ES6
- AMD
- RequrieJS
- r.js
- 模块化打包
- 学习Chrome DevTools
- chrome://inspect
- Chrome DevTools 之 Elements
- Chrome DevTools 之 Console
- Chrome DevTools 之 Sources
- Chrome DevTools 之 Network
- Chrome DevTools 之 Memory
- Chrome DevTools 之 Performance
- Chrome DevTools 之 Resources
- Chrome DevTools 之 Security
- Chrome DevTools 之 Audits
- 技巧
- Node.js
- 基础知识
- package.json 详解
- corepack
- npm
- yarn
- pnpm
- yalc
- 库处理
- Babel
- 相关库
- 转译基础
- 插件
- AST
- Rollup
- 基础
- 插件
- Webpack
- 详解配置
- 实现 loader
- webpack 进阶
- plugin 用法
- 辅助工具
- 解答疑惑
- 开发工具集合
- 花样百出的打包工具
- 纷杂的构建系统
- monorepo
- 前端工作流
- 爬虫
- 测试篇
- 综合
- Jest
- playwright
- Puppeteer
- cypress
- webdriverIO
- TestCafe
- 其他
- 工程开发
- gulp篇
- Building With Gulp
- Sass篇
- PostCSS篇
- combo服务
- 编码规范检查
- 前端优化
- 优化策略
- 高性能HTML5
- 浏览器端性能
- 前后端分离篇
- 分离部署
- API 文档框架
- 项目开发环境
- 基于 JWT 的 Token 认证
- 扯皮时间
- 持续集成及后续服务
- 静态服务器搭建
- mock与调试
- browserslist
- Project Starter
- Docker
- 文档网站生成
- ddd