然后我通过 Google 搜索测试相关的主题,找到了非常多的文章,但是我对于这些文章所介绍的深度并不满意。另外对于一个前端新手来说,我找不到一个综合性的教程能让前端小白逐步深入地进行应用测试。我想要找的是理论结合实践的前端测试教程。
所以我决定自己写一个前端测试系列。这里就是这一系列的开始(共 4 篇)。
一、什么是测试?
我把测试定义成:是一段检测你的应用代码(也叫“生产代码”)是否按预期执行的代码。有些人称之为 TDD(Test-Driven Development 或者 Test-Driven Design),但是 TDD 是一种特定的测试方法,它先写测试,然后用测试来驱动产品的设计和实现。
坦率地讲,我认为在生产代码完成之前写测试代码,还是在完成之后写测试代码并不重要。只要你写了足够多的测试样例测试你的生产代码,直到你对你的生产代码已经足够有信心就好。但是有很多人(包括我所尊敬的人)认为顺序很重要,这里我持自己的保留意见。
一个不好的现象是现在工业界已经把测试和 TDD 的概念混淆在一起,这样对于写生产代码的开发者所写的测试代码,就没有一个标准术语来称呼了。我倾向于叫它开发测试,或者普通测试。如果你对 “TDD vs 普通测试” 的讨论感兴趣,可以看这里,不过我建议你把我这个系列博文看完再参与讨论。
二、为什么测试?
我不打算在这里讨论为什么要进行测试。如果你不想写测试,那你就不写。不过你需要手动地一遍又一遍地测试你的 web 应用,这简直糟透了。那些讨厌的 bug,会不断地过来讨扰你。把这样的代码部署到生产环境,将是你噩梦的开始。
所以,我不打算深入讨论为什么要进行测试。
三、测试的类型
另外一个新手学习测试很容易有疑问的地方是:有很多种不同的测试类型。如果你提前做了点功课的话,你可能听说过(这里列出部分测试方法列表):单元测试、验收测试、集成测试、端到端测试、组件测试和服务测试。
更糟的是,当谈到了上面某一个具体的测试时,不同的人又有不同的理解。
这里再次说明我的观点,我认为叫什么名字都不重要,因为各种测试的定义都不难理解。所有的测试都分布于“测试光谱”中,光谱的一头是单元测试,另一头是端到端测试(后面统一称为 E2E 测试)。
四、测试光谱
1. 光谱的一端——单元测试
顾名思义,代码以单元为单位进行测试。那么什么是单元呢?这就不同的编程语言的定义不一样了。它可以是一个函数、一个模块、一个包或者一个类,甚至是一个对象(比如 JavaScript 和 Scala 语言)。在 JavaScript 中,通常是以类或者模块作为一个单元。
以单元进行测试很重要的一点是其测试是独立的。对于一些场景这种测试非常适合,比如算法、某些功能性函数(如字符串中有多少字符)和包含一组验证性功能的类等场景。
这些场景下进行独立的单元测试非常容易,因为他们不依赖于其他单元。但是假设一个单元依赖于其他单元怎么办?可以有两种做法:两个单元一起测试,或者 mock 另一个单元。
什么是 mock?下面我们举例来解释:
假设一个模块是一个单元,模块中包含了 writeSumToFile 这个函数,函数接收两个数字参数,并把他们的和写入文件中。
这里注意,这个模块自己并没有做写文件操作。写文件操作是在另一个单元 fileSumWriter 中做的。
那么为了测试第一个单元,我们既可以传一个真实的 fileSumWriter 进来,也可以模拟(mock)一个写文件操作(并不用真的实现写操作)。
如果我们传递一个 mock 到这个函数,那么这个单元测试,当然可以叫做“单元测试”,因为没有涉及到其他单元。但是如果两个单元一起测试,那么可能就有人说你这并不是单元测试了。
还是那句话,我不关心这到底应该叫什么。
2. 光谱的另一端——端到端测试
上面介绍了以一个单元为单位的测试。现在介绍端到端测试——测试整个应用。测试过程中,应用的所有配置会设置成和生产环境一样,应用中的一切都会被测试到。
这两个是“测试光谱”的两端。上面提到的其他测试方法,都是分布在这两个极端中间。他们的基本思路是逐步扩大测试范围,被测试的代码越来越多,mock 的代码越来越少。
很多人把这两个极端测试中间的部分叫做“集成测试”,但是对于 TDD 崇尚者们来说,集成测试是另一个完全不同的概念。在本系列文章中我将会使用这个概念模糊的名字——集成测试,具体说来就是:测试多个单元,但不是测试全部单元。
五、结语
那么,你的测试到底在什么测试层级上呢?很多人说有一个测试金字塔——大量的单元测试,少部分的集成测试,非常小部分的端到端测试。但是我不想讨论这些,这个系列文章我希望讨论的是如何对前端代码进行单元测试、集成测试和端到端测试。
接下来的文章,第一篇将会介绍前端单元测试,第二篇会介绍端到端测试,第三篇会介绍集成测试。