diff --git a/1-js/03-code-quality/05-testing-mocha/3-pow-test-wrong/solution.md b/1-js/03-code-quality/05-testing-mocha/3-pow-test-wrong/solution.md index f993fee0a8..ec29252976 100644 --- a/1-js/03-code-quality/05-testing-mocha/3-pow-test-wrong/solution.md +++ b/1-js/03-code-quality/05-testing-mocha/3-pow-test-wrong/solution.md @@ -1,12 +1,12 @@ -这些测试代码演示了开发人员在编写测试代码时遇到的一些疑惑。 +这些测试代码展示了开发人员在编写测试代码时遇到的一些疑惑。 我们这里实际上有三条测试,但是用了一个函数来放置 3 个断言语句。 -有时用这种方式编写会更容易,但是如果发生错误,那么出错的情况就不那么明显了。 +有时用这种方式编写会更容易,但是如果发生错误,那么到底什么出错了就很不明显。 -如果在复杂的执行流程中发生了一个错误,那么我们必须在那找出数据。 我们实际上必须**调试测试**。 +如果错误发生在一个复杂的执行流的中间,那么我们就必须找出那个点的数据。我们必须 **调试测试**。 -将测试分成多个具有明确输入和输出的 `it` 代码块中会更好。 +将测试分成多个具有明确输入和输出的 `it` 代码块会更好。 像是这样: ```js @@ -25,9 +25,9 @@ describe("Raises x to power n", function() { }); ``` -我们使用 `describe` 和一组 `it` 代码块替换掉了单个的 `it`。现在,如果某个测试失败了,我们会清楚地看到数据是什么。 +我们使用 `describe` 和一组 `it` 代码块替换掉了单个的 `it`。现在,如果某个测试失败了,我们可以清楚地看到数据是什么。 -此外,我们可以通过编写`it.only` 而不是 `it` 来隔离单个测试并以独立模式运行它: +此外,我们可以通过编写 `it.only` 而不是 `it` 来隔离单个测试,并以独立模式运行它: ```js diff --git a/1-js/03-code-quality/05-testing-mocha/3-pow-test-wrong/task.md b/1-js/03-code-quality/05-testing-mocha/3-pow-test-wrong/task.md index 986a421db4..bb27e89a42 100644 --- a/1-js/03-code-quality/05-testing-mocha/3-pow-test-wrong/task.md +++ b/1-js/03-code-quality/05-testing-mocha/3-pow-test-wrong/task.md @@ -4,7 +4,7 @@ importance: 5 # 测试代码中有什么错误? -下面测试代码中的 `pow` 有什么错误? +下面这个 `pow` 的测试代码有什么错误? ```js it("Raises x to the power n", function() { @@ -21,4 +21,4 @@ it("Raises x to the power n", function() { }); ``` -附:从语法上来说这些测试代码是正确且能通过的。 +附:从语法上来说这些测试代码是正确且通过的。 diff --git a/1-js/03-code-quality/05-testing-mocha/article.md b/1-js/03-code-quality/05-testing-mocha/article.md index 988534045f..d917e76f4c 100644 --- a/1-js/03-code-quality/05-testing-mocha/article.md +++ b/1-js/03-code-quality/05-testing-mocha/article.md @@ -1,8 +1,6 @@ -# 使用 mocha 进行自动化测试 +# 使用 Mocha 进行自动化测试 -自动化测试在任务中将会被进一步使用。 - -它实际上是一个开发者的“教育最低限度”的一部分。 +自动化测试将被用于进一步的任务中,并且还将被广泛应用在实际项目中。 ## 为什么我们需要测试? @@ -16,29 +14,29 @@ **当通过手动重新运行来测试代码时,很容易漏掉一些东西。** -例如,我们要创建一个函数 `f`。写一写代码,然后测试:`f(1)` 可以执行,但是 `f(2)` 不执行。我们修复了一下代码,现在 `f(2)` 可以执行了。看起来已经搞定了?但是我们忘了重新测试 `f(1)`。这样有可能会导致一个错误。 +例如,我们要创建一个函数 `f`。写一些代码,然后测试:`f(1)` 可以执行,但是 `f(2)` 不执行。我们修复了一下代码,现在 `f(2)` 可以执行了。看起来已经搞定了?但是我们忘了重新测试 `f(1)`。这样有可能会导致出现错误。 -这是非常典型的。当我们在开发一些东西时,我们会保留很多可能需要的用例和想法。但是不要想着程序员在每一次改变之后都去检查所有的案例。所以很容易造成修复了一个问题却造成另一个问题的情况。 +这是非常典型的。当我们在开发一些东西时,我们会保留很多可能需要的用例。但是不要想着程序员在每一次代码修改后都去检查所有的案例。所以这就很容易造成修复了一个问题却造成另一个问题的情况。 -**自动化测试意味着除了代码之外,测试是单独写的。它们可以很容易地执行,并检查所有的主要用例。** +**自动化测试意味着测试是独立于代码的。它们以各种方式运行我们的函数,并将结果与预期结果进行比较。** ## 行为驱动开发(BDD) -我们来使用一种名为[行为驱动开发](http://en.wikipedia.org/wiki/Behavior-driven_development)或简而言之 BDD 的技术。许多项目都采用这种方法。BDD 不仅仅是测试,还包含更多东西。 +我们来使用一种名为 [行为驱动开发](http://en.wikipedia.org/wiki/Behavior-driven_development) 或简言为 BDD 的技术。 -**BDD 包含了三部分:测试、文档和示例。** +**BDD 包含了三部分内容:测试、文档和示例。** -说的已经足够了,让我们来看一下例子吧。 +为了理解 BDD,我们将研究一个实际的开发案例。 -## 开发中的 “pow”:规范 +## 开发 “pow”:规范 -我们想要创建一个函数 `pow(x, n)` 来计算 `x` 的整数 `n` 次幂。我们假设 `n≥0`。 +我们想要创建一个函数 `pow(x, n)` 来计算 `x` 的 `n` 次幂(`n` 为整数)。我们假设 `n≥0`。 -这个任务只是一个例子:JavaScript 中有一个 `**` 操作符可以做到。但是在这里我们专注于可以很好的应用于更复杂任务的开发流程上。 +这个任务只是一个例子:JavaScript 中有一个 `**` 操作符可以用于幂运算。但是在这里我们专注于可以应用于更复杂任务的开发流程上。 在创建函数 `pow` 的代码之前,我们可以想象函数应该做什么并且描述出来。 -这样的描述被称作**规范**,看起来像这样: +这样的描述被称作 **规范(specification, spec)**,包含用例的描述以及针对它们的测试,如下所示: ```js describe("pow", function() { @@ -50,71 +48,73 @@ describe("pow", function() { }); ``` -一个规范包含三个主要的模块,你可以在上面看到。 +正如你所看到的,一个规范包含三个主要的模块。: `describe("title", function() { ... })` -: 表示我们正在描述的功能是什么。用于组织 "工人(workers)" -- `it` 代码块。在我们的例子中我们正在描述函数 `pow`。 +: 表示我们正在描述的功能是什么。在我们的例子中我们正在描述函数 `pow`。用于组织“工人(workers)” —— `it` 代码块。 -`it("title", function() { ... })` -: `it` 里面的 "title" 中我们以**人类可读**的方式描述特定的用例,第二个参数是一个测试它的函数。 +`it("use case description", function() { ... })` +: `it` 里面的描述部分,我们以一种 **易于理解** 的方式描述特定的用例,第二个参数是用于对其进行测试的函数。 `assert.equal(value1, value2)` -: `it` 块中的代码。如果实现是正确的,它应该在执行的时候不产生任何错误。 +: `it` 块中的代码,如果实现是正确的,它应该在执行的时候不产生任何错误。 - `assert.*` 函数用于检查 `pow` 是否按照预期工作。在这里我们使用了其中之一 —— `assert.equal`,它会比较参数,如果它们不相等则会抛出一个错误。这里它检查了 `pow(2, 3)` 的值是否等于 `8`。 + `assert.*` 函数用于检查 `pow` 函数是否按照预期工作。在这里我们使用了其中之一 —— `assert.equal`,它会对参数进行比较,如果它们不相等则会抛出一个错误。这里它检查了 `pow(2, 3)` 的值是否等于 `8`。还有其他类型的比较和检查,我们将在后面介绍到。 - 还有其他类型的比较和检查方法,我们以后将会了解到。 +规范可以被执行,它将运行在 `it` 块中指定的测试。我们稍后会看到。 ## 开发流程 开发流程通常看起来像这样: 1. 编写初始规范,测试最基本的功能。 -2. 创建一个最初始实现。 -3. 检查它是否工作,我们运行测试框架 [Mocha](http://mochajs.org/)(很快会有更多细节)来运行测试。错误会被显示出来。我们持续修正直到一切都能工作。 -4. 现在我们有一个基于测试的能工作的初步实现。 -5. 我们增加更多的用例到规范中,或许目前的程序实现还不支持。测试从失败开始。 -6. 进行第 3 步,更新程序直到测试不会抛出错误。 +2. 创建一个最初始的实现。 +3. 检查它是否工作,我们运行测试框架 [Mocha](http://mochajs.org/)(很快会有更多细节)来运行测试。当功能未完成时,将显示错误。我们持续修正直到一切都能工作。 +4. 现在我们有一个带有测试的能工作的初步实现。 +5. 我们增加更多的用例到规范中,或许目前的程序实现还不支持。无法通过测试。 +6. 回到第 3 步,更新程序直到测试不会抛出错误。 7. 重复第 3 步到第 6 步,直到功能完善。 -如此来看,开发是**迭代**的。我们写规范,实现它,确保测试通过,然后写更多的测试来确保它们工作等等。最后,我们有了一个能工作的实现和针对它的测试。 +如此来看,开发就是不断地 **迭代**。我们写规范,实现它,确保测试通过,然后写更多的测试,确保它们工作等等。最后,我们有了一个能工作的实现和针对它的测试。 + +让我们在我们的开发案例中看看这个开发流程吧。 -在我们的案例中,第一步已经完成了:针对 `pow` 我们有一个初始规范。因此让我们来实现它吧。但在此之前,让我们做一个针对规范的“零”运行,只是为了看到测试正在运行(它们都会失败)。 +在我们的案例中,第一步已经完成了:我们有一个针对 `pow` 的初始规范。因此让我们来实现它吧。但在此之前,让我们用一些 JavaScript 库来运行测试,就是看看测试是通过了还是失败了。 ## 行为规范 在本教程中,我们将使用以下 JavaScript 库进行测试: -- [Mocha](http://mochajs.org/) —— 核心框架:提供了包括 `describe` 和 `it` 的通用型测试函数和运行测试的主函数。 -- [Chai](http://chaijs.com) —— 提供很多断言支持的库。它可以用很多不同的断言。现在我们只需要用 `assert.equal`。 -- [Sinon](http://sinonjs.org/) —— 用于监视函数、模拟内置函数和其他函数的库,我们稍后会用到它。 +- [Mocha](http://mochajs.org/) —— 核心框架:提供了包括通用型测试函数 `describe` 和 `it`,以及用于运行测试的主函数。 +- [Chai](http://chaijs.com) —— 提供很多断言(assertion)支持的库。它提供了很多不同的断言,现在我们只需要用 `assert.equal`。 +- [Sinon](http://sinonjs.org/) —— 用于监视函数、模拟内置函数和其他函数的库,我们在后面才会用到它。 -这些库都同时适用于浏览器端和服务器端。这里我们使用浏览器端。 +这些库都既适用于浏览器端,也适用于服务器端。这里我们将使用浏览器端的变体。 包含这些框架和 `pow` 规范的完整的 HTML 页面: ```html src="index.html" ``` -该页面可分为四部分: +该页面可分为五个部分: -1. `
` -- 为测试添加第三方库和样式文件。 -2. ` diff --git a/1-js/03-code-quality/05-testing-mocha/pow-4.view/test.js b/1-js/03-code-quality/05-testing-mocha/pow-4.view/test.js index 10a032d03a..e5ce2ce433 100644 --- a/1-js/03-code-quality/05-testing-mocha/pow-4.view/test.js +++ b/1-js/03-code-quality/05-testing-mocha/pow-4.view/test.js @@ -1,6 +1,6 @@ describe("pow", function() { - describe("raises x to power n", function() { + describe("raises x to power 3", function() { function makeTest(x) { let expected = x * x * x; diff --git a/1-js/03-code-quality/05-testing-mocha/pow-full.view/test.js b/1-js/03-code-quality/05-testing-mocha/pow-full.view/test.js index a5a3459795..75ff5e99fd 100644 --- a/1-js/03-code-quality/05-testing-mocha/pow-full.view/test.js +++ b/1-js/03-code-quality/05-testing-mocha/pow-full.view/test.js @@ -1,6 +1,6 @@ describe("pow", function() { - describe("raises x to power n", function() { + describe("raises x to power 3", function() { function makeTest(x) { let expected = x * x * x; diff --git a/1-js/03-code-quality/05-testing-mocha/pow-nan.view/test.js b/1-js/03-code-quality/05-testing-mocha/pow-nan.view/test.js index a5a3459795..75ff5e99fd 100644 --- a/1-js/03-code-quality/05-testing-mocha/pow-nan.view/test.js +++ b/1-js/03-code-quality/05-testing-mocha/pow-nan.view/test.js @@ -1,6 +1,6 @@ describe("pow", function() { - describe("raises x to power n", function() { + describe("raises x to power 3", function() { function makeTest(x) { let expected = x * x * x;