> For the complete documentation index, see [llms.txt](https://suki.gitbook.io/notes/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://suki.gitbook.io/notes/articles/unit-test/notes_for_testing_vuejs_applications_1.md).

# Test Vuejs Application - Chapter 1

* 测试是什么
* 测试有什么用
* 单元测试、e2e 测试、snapshot 测试的区别

## 概念

测试就是检查程序的行为是否符合预期的过程。

测试分为两种：手动测试和自动化测试。手动测试就是自己拿鼠标点点点，跟程序进行交互，检查程序的反应是否符合预期。自动化测试就是编写程序来替代手动检查。

> user journey: a list of steps that a user can take through an application. eg. open applicationn, fill out form, click submit.

## e2e 测试

e2e 测试是指从用户的角度出发，将用户的行为自动化，比如用程序模拟用户打开浏览器、填写表单、提交表单等操作。

**不足**

1. 耗时长。打开浏览器、请求网页都是比较耗时的操作。
2. debug 难。因此 e2e 测试最好是在 Docker 容器中运行，便于重现 bug。
3. 脆弱。指的是即使程序正常运行，e2e 测试还是可能不通过，比如后端接口暂时奔溃可能会导致测试结果不通过。

## 单元测试

单元测试把程序拆分成小部分(单元)，再对这些部分进行分别测试。一般可测试的单元指的是函数，不过在 Vue 中，可测试单元也包括组件。

**优点**

1. 运行时间快。
2. 测试代码天然就是源码的文档。
3. 可靠。只要源码的功能不变，单元测试的结果就会保持一致，这点跟 e2e 测试不一样。

**不足**

1. 影响代码重构的效率。如果要重构代码，相应的测试代码也需要更新。(thoughts: 所以写单元测试的时候尽量不要去测试实现细节，这样即使一个模块的实现方式变了，只要它的功能不变，测试就还是有效的。)
2. 单元测试把程序拆分成小块来测试，保证了每个部分的行为符合预期，但不保证它们合起来作用也符合预期，这也是为什么我们不能单独依赖单元测试，还需要 e2e 测试的原因。

## snapshot 测试

snapshot 测试就像是“找不同”游戏，它会将当前运行的程序进行“截图”，与之前保存的“截图”进行对比，如果两者不一致则测试不通过。

传统的 snapshot 测试就真的是打开浏览器，加载程序，屏幕截图，对比截图。但这样做的缺点很明显，不同操作系统或者不同版本的浏览器也会影响渲染结果，所以测试结果不完全可靠。

而 jest 的 snapshot 测试则是通过对比 JS 中的**可序列化(serializable)**&#x503C;，不受操作系统和浏览器的影响。

> serializable means any code that can be converted to a string and then back into a value. In reality, it refers to a V8 method. (question: Is it similar to the stringify method of JSON?)

## 测试金字塔

项目中的测试代码组成部分应该是：

* \~10% e2e 测试
* \~30% snapshot 测试
* \~60% 单元测试

> 还有一种测试叫**集成测试(integration tests)**，但并不太建议在前端使用。

## TDD

Test-driven development

一个**参考**的流程：

1. 决定需要什么样的组件
2. 针对组件写单元测试和源码
3. 增加样式
4. 增加 snapshot 测试
5. 手动测试
6. 增加 e2e 测试

## 测试覆盖率

100% 的测试覆盖率可能是个伪命题。

达到 100% 测试覆盖率是很“劳民伤财”的，除非是非常重要的应用，比如支付相关的应用，一般我们没必要追求 100% 的覆盖率，而且 100% 的覆盖率也不能保证程序完全没有 bug。

## 什么该测试

一个基本的概念是，我们应该给组件提供**输入**，然后测试它的**输出**是否符合我们的预期。

**常见输入**

* 组件的 props
* 用户触发的事件，比如鼠标点击
* Vue 中的自定义事件
* Vuex 中的数据

**常见输出**

* 组件触发了事件
* 组件提供了外部函数而且这个函数在外部被调用了
