前言
哈喽,大家好,我是海怪。
最近有不少朋友找到我聊了聊测试相关的内容,发现他们对测试的分类有些迷茫。实际上测试一共就 3 种:E2E,集成,单测,其它的功能测试、UI 测试、界面测试只是它们中里面的一种。
Kent C. Dodds
在这篇文章 《Static vs Unit vs Integration vs E2E Testing for Frontend Apps》
也聊到了这 3 种测试的对比和区别,除此之外,还聊到它们各自的适用场景,应该对还在迷茫中的同学有所帮助。所以今天把这篇文章分享给大家~
翻译中会尽量用更地道的语言,这也意味着会给原文加一层 Buf,想看原文的可点击 这里。
正片开始
J.B. Rainsberger 在我的采访里说了一个我很喜欢的比喻:
你可以把油漆扔到墙上,最终你可能会涂到大部分的墙壁,但除非你用刷子来刷墙,否则你永远不会刷到角落。
我喜欢用它来类比测试,因为做测试就跟刷墙一样,在开始之前要选择正确的策略。你会用小刷头来刷墙么?当然不会。那会花很长时间,而且效果也不均匀。
那你会用滚筒来刷所有东西么?比如拿它来刷两百年前你的曾曾祖母从别的地方带来的豪华家具?绝对不会。不同的刷子适用不同的场景,测试也是如此。
这就是为什么我会构建这个 测试模型。
在这个模型里,有 4 种测试分类:
- 端对端测试:利用一个很像用户行为的机器人来和 App 交互,并验证功能是否正常。有时也会说 “功能测试” 或 E2E。
- 集成测试:验证多个单元是否能协调共同工作。
- 单元测试:验证单独隔离的部分是否正常工作。
- 静态测试:捕获写代码时的错别字和类型错误
在这个模型里,每个测试分类的大小和你在测试时的关注度呈正相关(通常来说)。下面我来深入地聊聊这几种测试类型的区别、含义、以及如何对它们做优化。
测试类型
让我们从上往下看几个这类测试的例子:
端对端测试
一般来说,它会跑完整个应用(前端 + 后端),这样的测试会像真实用户那样和应用进行交互。下面的例子是用 Cypresss 来实现的:
import {
generate} from 'todo-test-utils'
describe('todo app', () => {
it('should work for a typical user', () => {
const user = generate.user()
const todo = generate.todo()
// 这里我们会走通整个注册流程
// 我一般只会写一个测试来这么做
// 剩下的测试则会通过直接发 HTTP 请求来实现注册功能
// 这样我们就可以跳过这个注册表单的交互过程了
cy.visitApp()
cy.findByText(/register/i).click()
cy.findByLabelText(/username/i).type(user.username)
cy.findByLabelText(/password/i).type(user.password)
cy.findByText(/login/i).click()
cy.findByLabelText(/add todo/i)
.type(todo.description)
.type('{enter}')
cy.findByTestId('todo-0'