开发指南-测试 初译完毕

This commit is contained in:
Zhicheng Wang 2016-05-30 19:23:17 +08:00
parent 1f1b3e8496
commit f5e25c2371
4 changed files with 105 additions and 8 deletions

View File

@ -1323,7 +1323,7 @@ code-example(format="").
在`index.html`中我们启用SystemJS。添加一组用于加载SystemJS库和一个为它加载配置文件的`<script>`标签。 在`index.html`中我们启用SystemJS。添加一组用于加载SystemJS库和一个为它加载配置文件的`<script>`标签。
然后添加更多的`<script>`标签以通过SystemJS加载我们的应用。 然后添加更多的`<script>`标签以通过SystemJS加载我们的应用。
它将会*替换掉*我们以前用来为应用程序加载件的许多`<script>`标签。 它将会*替换掉*我们以前用来为应用程序加载件的许多`<script>`标签。
+makeExample('upgrade-phonecat/ts/typescript-conversion/app/index.html', 'scripts', 'app/index.html') +makeExample('upgrade-phonecat/ts/typescript-conversion/app/index.html', 'scripts', 'app/index.html')
@ -1532,7 +1532,7 @@ code-example(format="").
这个项目中同时有基于Protractor的E2E测试和一些基于Karma的单元测试。 这个项目中同时有基于Protractor的E2E测试和一些基于Karma的单元测试。
对这两者来说E2E测试的转换要快得多根据定义E2E测试通过与应用中显示的这些UI元素互动从*外部*访问我们的应用来进行测试。 对这两者来说E2E测试的转换要快得多根据定义E2E测试通过与应用中显示的这些UI元素互动从*外部*访问我们的应用来进行测试。
E2E测试实际上并不关心这些应用代码的内部结构。这也意味着,虽然我们已经修改了一点儿此应用程序, E2E测试实际上并不关心这些应用中各部件的内部结构。这也意味着,虽然我们已经修改了一点儿此应用程序,
但是E2E测试套件仍然应该能像以前一样全部通过。因为从用户的角度来说我们并没有改变应用的行为。 但是E2E测试套件仍然应该能像以前一样全部通过。因为从用户的角度来说我们并没有改变应用的行为。
For unit tests, on the other hand, we'll do a bit of conversion work. For unit tests, on the other hand, we'll do a bit of conversion work.
@ -2634,7 +2634,7 @@ table
but there isn't really any need for that anymore, and we can begin to but there isn't really any need for that anymore, and we can begin to
pull out the last remnants of Angular 1. pull out the last remnants of Angular 1.
此时我们已经把所有的Angular 1程序代码替换成了它们在Angular 2中的对应物。该应用仍然是作为混合应用进行引导的 此时我们已经把所有的Angular 1程序的各部件替换成了它们在Angular 2中的对应物。该应用仍然是作为混合应用进行引导的
但实际上我们已经不需要它了我们这就彻底移除Angular 1的残余势力。 但实际上我们已经不需要它了我们这就彻底移除Angular 1的残余势力。
There are just two more things to do: We need to switch the router to There are just two more things to do: We need to switch the router to

View File

@ -7,7 +7,7 @@
}, },
"jasmine-testing-101": { "jasmine-testing-101": {
"title": "Jasmine测试101", "title": "Jasmine测试101(译注:国外大学中最基础的课号通常是101)",
"intro": "用Jasmine测试任何东西时所需的基础知识" "intro": "用Jasmine测试任何东西时所需的基础知识"
}, },

View File

@ -35,8 +35,8 @@ include ../_util-fns
the [Tour of Heroes](../tutorial/) tutorial the [Tour of Heroes](../tutorial/) tutorial
such as <code>npm</code>, <code>gulp</code>, and <code>live-server</code>. such as <code>npm</code>, <code>gulp</code>, and <code>live-server</code>.
这一章单元测试是在其它章节的基础上写的。我们建议你按顺序阅读它们。同时我们假设你已经对Angular 2的原理、[“快速起步”](../quickstart.html)中介绍的工具、 这一章单元测试是在其它章节的基础上写的。我们建议你按顺序阅读它们。同时我们假设你已经对Angular 2的原理、[“快速起步”](../quickstart.html)
[英雄指南](../tutorial)<code>npm</code>、<code>gulp</code>和<code>live-server</code>等工具都已经有所了解。 [英雄指南](../tutorial)中介绍的<code>npm</code>、<code>gulp</code>和<code>live-server</code>等工具都已经有所了解。
.l-main-section .l-main-section
:marked :marked

View File

@ -93,87 +93,146 @@ include ../_util-fns
the [Tour of Heroes](../tutorial/) tutorial the [Tour of Heroes](../tutorial/) tutorial
such as <code>npm</code>, <code>gulp</code>, and <code>live-server</code>. such as <code>npm</code>, <code>gulp</code>, and <code>live-server</code>.
这一章单元测试是在其它章节的基础上写的。我们建议你按顺序阅读它们。同时我们假设你已经对Angular 2的原理、[“快速起步”](../quickstart.html)中介绍的工具、 这一章单元测试是在其它章节的基础上写的。我们建议你按顺序阅读它们。同时我们假设你已经对Angular 2的原理、[“快速起步”](../quickstart.html)
[英雄指南](../tutorial)<code>npm</code>、<code>gulp</code>和<code>live-server</code>等工具都已经有所了解。 [英雄指南](../tutorial)中介绍的<code>npm</code>、<code>gulp</code>和<code>live-server</code>等工具都已经有所了解。
:marked :marked
## Add another spec file ## Add another spec file
## 添加另一个规约文件
**Create** a `my-uppercase.pipe.spec.ts` in `app/`. **Create** a `my-uppercase.pipe.spec.ts` in `app/`.
在`app/`中创建一个`my-uppercase.pipe.spec.ts`文件。
**Stop and restart the TypeScript compiler** to ensure we compile the new file. **Stop and restart the TypeScript compiler** to ensure we compile the new file.
**停止并重新启动TypeScript编译器**以确保我们能编译这个新文件。
**Add** the following lines of rather obvious Jasmine test code. **Add** the following lines of rather obvious Jasmine test code.
**添加**下面这些直白的Jasmine测试代码。
+makeExample('testing/ts/app/my-uppercase.pipe.spec.ts', 'base-pipe-spec', 'app/my-uppercase.pipe.spec.ts') +makeExample('testing/ts/app/my-uppercase.pipe.spec.ts', 'base-pipe-spec', 'app/my-uppercase.pipe.spec.ts')
:marked :marked
Note that each test is short (one line in our case). Note that each test is short (one line in our case).
It has a clear label that accurately describes the test. And it makes exactly one expectation. It has a clear label that accurately describes the test. And it makes exactly one expectation.
注意,每个测试都很短(在这里是一行)。
它有一个清晰的用来精确描述本测试的标签,并且只表达一条期待。
Anyone can read these tests and understand quickly what the test does and what the pipe does. Anyone can read these tests and understand quickly what the test does and what the pipe does.
If one of the tests fails, we know which expected behavior is no longer true. If one of the tests fails, we know which expected behavior is no longer true.
Well have little trouble maintaining these tests and adding more like them as we encounter new conditions to explore. Well have little trouble maintaining these tests and adding more like them as we encounter new conditions to explore.
任何人都可以读这些测试,并快速理解这个测试是做什么的,以及这个管道是做什么的。
如果这些测试之一失败了,我们就知道它所期待的行为出问题了。
要维护这些测试我们会遇到一些小麻烦,并且如果我们遇到了需要探索的新条件,还得添加更多类似的测试。
Thats the way we like our tests! Thats the way we like our tests!
但这就是我们关爱这些测试的方式!
## Add this spec to `unit-tests.html` ## Add this spec to `unit-tests.html`
## 把规约添加到`unit-tests.html`中
Now lets wire our new spec file into the HTML test harness. Now lets wire our new spec file into the HTML test harness.
现在让我们把这个新的规约文件放进这个HTML测试挽具中。
Open `unit-tests.html`. Find `System.import('app/hero.spec')`. Open `unit-tests.html`. Find `System.import('app/hero.spec')`.
打开`unit-tests.html`。查找`System.import('app/hero.spec')`。
Hmm. We cant just add `System.import('app/my-uppercase.pipe.spec')`. Hmm. We cant just add `System.import('app/my-uppercase.pipe.spec')`.
恩……我们不能只添加`System.import('app/my-uppercase.pipe.spec')`。
The first `System.import` returns a promise as does this second import. The first `System.import` returns a promise as does this second import.
We cant run any of the Jasmine tests until **both imports are finished**. We cant run any of the Jasmine tests until **both imports are finished**.
第一个`System.import`返回一个承诺(promise),第二个也一样。
直到**这两个`import`都执行完**Jasmine的测试才会开始运行。
Fortunately, we can create a new `Promise` that wraps both import promises and waits Fortunately, we can create a new `Promise` that wraps both import promises and waits
for both to finish loading. for both to finish loading.
幸运的是,我们可以创建一个新的`Promise`来包装这两个`import`语句返回的承诺,并等它们两个加载结束。
+makeExample('testing/ts/unit-tests-4.html', 'promise-all')(format=".") +makeExample('testing/ts/unit-tests-4.html', 'promise-all')(format=".")
:marked :marked
We have a pattern for adding new tests. We have a pattern for adding new tests.
这下我们有了一种添加新测试的模式。
In future, when we add a new spec, we add another `System.import('app/some.spec')` to In future, when we add a new spec, we add another `System.import('app/some.spec')` to
the array argument passed to `Promise.all`. the array argument passed to `Promise.all`.
将来我们再添加新的规约时,只要往传给`Promise.all`的数组参数中添加另一个`System.import('app/some.spec')`语句就可以了。
Try it. The browser should refresh and show the following in the console: Try it. The browser should refresh and show the following in the console:
试一下。浏览器会刷新,并在控制台中显示如下内容:
code-example(format="" language="html" escape="html"). code-example(format="" language="html" escape="html").
GET http://localhost:8080/app/my-uppercase.pipe.js 404 (Not Found) GET http://localhost:8080/app/my-uppercase.pipe.js 404 (Not Found)
:marked :marked
Our test failed, as expected. We're importing something that doesn't exist and our test fails saying that. All is going according to plan. Our test failed, as expected. We're importing something that doesn't exist and our test fails saying that. All is going according to plan.
如预期的一样,测试失败了。我们在导入一些不存在的东西,就像测试的失败信息中所说的那样。一切都在按照计划发生。
:marked :marked
## The pipe, if you please ## The pipe, if you please
## 管道,请上场
The test is asking for a pipe, and we shall deliver. The test is asking for a pipe, and we shall deliver.
这个测试需要一个管道,我们这就给它。
**Create** a `my-uppercase.pipe.ts` in `app/`. **Create** a `my-uppercase.pipe.ts` in `app/`.
在`app/`中**创建**一个`my-uppercase.pipe.ts`文件。
**Stop and restart the TypeScript compiler** to ensure we compile the new file. **Stop and restart the TypeScript compiler** to ensure we compile the new file.
**停止并重启TypeScript编译器**,以确保我们能编译这个新文件。
**Add** a basic pipe that doesn't do anything. We know how to make strings uppercase, but we since we're letting the test take the lead let's wait for it to tell us what's next. Maybe it'll surprise us. **Add** a basic pipe that doesn't do anything. We know how to make strings uppercase, but we since we're letting the test take the lead let's wait for it to tell us what's next. Maybe it'll surprise us.
**添加**一个什么也不做的基本管道。我们知道该如何让字符串变大写,但由于要让测试先行,所以就让测试来告诉我们下一步做什么。也许它会带给我们一些惊喜。
+makeExample('testing/ts/app/my-uppercase.pipe.1.ts', null, 'app/my-uppercase.pipe.ts') +makeExample('testing/ts/app/my-uppercase.pipe.1.ts', null, 'app/my-uppercase.pipe.ts')
:marked :marked
Reload our test page and... Reload our test page and...
刷新我们的测试页面,并且……
code-example(format="" language="html" escape="html"). code-example(format="" language="html" escape="html").
GET http://localhost:8080/angular2/core 404 (Not Found) GET http://localhost:8080/angular2/core 404 (Not Found)
:marked :marked
## The Angular library, if you please ## The Angular library, if you please
## Angular库请上场
Looking back at `unit-tests.html` we realize that we have not loaded the Angular library. Looking back at `unit-tests.html` we realize that we have not loaded the Angular library.
Yet we were able to load and test the applications `Hero` interface. Yet we were able to load and test the applications `Hero` interface.
往回看`unit-tests.html`我们认识到自己还没加载过Angular库。
但我们甚至都已经能加载应用中`Hero`接口的测试了。
**We were lucky!** The `Hero` interface has no dependence on Angular. **We were lucky!** The `Hero` interface has no dependence on Angular.
If it had depended on Angular, wed still be staring at the Jasmine “big-time fail” screen: If it had depended on Angular, wed still be staring at the Jasmine “big-time fail” screen:
**那是我们幸运!**`Hero`接口并不依赖Angular。
如果它依赖于Angular当初我们就得从Jasmine的“大败局”界面开始了
figure.image-display figure.image-display
img(src='/resources/images/devguide/testing-an-angular-pipe/big-time-fail-screen.png' img(src='/resources/images/devguide/testing-an-angular-pipe/big-time-fail-screen.png'
alt="Jasmine's' big time fail screen") alt="Jasmine's' big time fail screen")
@ -182,30 +241,46 @@ figure.image-display
We are writing an Angular application after all and We are writing an Angular application after all and
we were going to need Angular sooner or later. That time has come. we were going to need Angular sooner or later. That time has come.
毕竟我们写的是Angular程序迟早会需要Angular登场。对就是现在
`MyUppercasePipe` depends on Angular as is clear in the first few lines: `MyUppercasePipe` depends on Angular as is clear in the first few lines:
在开始的寥寥几行中,`MyUppercasePipe`对Angular的依赖就清晰可见了
+makeExample('testing/ts/app/my-uppercase.pipe.ts', 'depends-on-angular')(format=".") +makeExample('testing/ts/app/my-uppercase.pipe.ts', 'depends-on-angular')(format=".")
:marked :marked
**Open** `unit-tests.html` **Open** `unit-tests.html`
**打开**`unit-tests.html`
**Find** the `<!-- #1. add the system.js library -->` comment. **Find** the `<!-- #1. add the system.js library -->` comment.
**查找**`<!-- #1. add the system.js library -->`注释。
**Replace** the scripts tags beneath it with the all the needed angular scripts: **Replace** the scripts tags beneath it with the all the needed angular scripts:
把它下方的`script`标记**替换成**这些所需的Angular脚本
+makeExample('testing/ts/unit-tests-5.html', 'import-angular')(format=".") +makeExample('testing/ts/unit-tests-5.html', 'import-angular')(format=".")
:marked :marked
We should now be ready to see our 3 expectations fail when reloading our test page. We should now be ready to see our 3 expectations fail when reloading our test page.
当刷新测试页面时,我们会期待看到三条期待都落空了。
figure.image-display figure.image-display
img(src='/resources/images/devguide/testing-an-angular-pipe/two-failures.png' alt="2 failed tests") img(src='/resources/images/devguide/testing-an-angular-pipe/two-failures.png' alt="2 failed tests")
:marked :marked
## Uppercase, if you please ## Uppercase, if you please
## Uppercase请上场
The first two tests that passed were our old `hero` interface tests, so it makes sense that those passed. Of our three new expectations, one still passed though. The first two tests that passed were our old `hero` interface tests, so it makes sense that those passed. Of our three new expectations, one still passed though.
前两个通过的测试是我们以前的`hero`接口测试,所以它们的通过是有意义的。当然,这三条新的期待中,有一条还是通过了。
``` ```
MyUppercasePipe MyUppercasePipe
transforms "abc" to "ABC" transforms "abc" to "ABC"
@ -216,30 +291,52 @@ figure.image-display
Ah but of course! Our simple pipe doesn't transform the input at all, and the third test expected Ah but of course! Our simple pipe doesn't transform the input at all, and the third test expected
input to not be changed. input to not be changed.
啊,当然!我们这个简单的管道还完全没有转换输入,而第三条测试期待的是输入内容没变化。
All we have to do now is actually transform text to uppercase in our pipe. All we have to do now is actually transform text to uppercase in our pipe.
我们现在要做的一切,实际上是在我们的管道中把这些文本转换成大写。
+makeExample('testing/ts/app/my-uppercase.pipe.ts', 'uppercase')(format=".") +makeExample('testing/ts/app/my-uppercase.pipe.ts', 'uppercase')(format=".")
:marked :marked
Are we done now? Are we done now?
现在,我们完成了吗?
figure.image-display figure.image-display
img(src='/resources/images/devguide/testing-an-angular-pipe/zero-failures.png' alt="0 failed tests") img(src='/resources/images/devguide/testing-an-angular-pipe/zero-failures.png' alt="0 failed tests")
:marked :marked
The glorious green is back with us again! The glorious green is back with us again!
我们光荣的绿条儿又回来了!
We tried a bit of test driven development and it seems to have guided us to success. We tried a bit of test driven development and it seems to have guided us to success.
我们尝试了一点点测试驱动开发,看起来它确实指导我们走向了成功。
But it's not always feasible. For instance, sometimes we need to write tests for existing functionality, like what we're about to do with the rest of Tour of Heroes. But it's not always feasible. For instance, sometimes we need to write tests for existing functionality, like what we're about to do with the rest of Tour of Heroes.
但这也并不总是可行的。比如,优势我们需要为现有功能写测试,就像我们即将对《英雄指南》的其余部分所做的那样。
If we are writing new code though, writing tests might just be what we need to help us track our progress and keep the end result in sight at all times. If we are writing new code though, writing tests might just be what we need to help us track our progress and keep the end result in sight at all times.
如果我们正在写新代码,写测试可以帮助我们追踪进度和保持最终结果全程可见。
:marked :marked
## Whats Next? ## Whats Next?
## 接下来呢?
Now we can test parts of our application that we *load* asynchronously with system.js. Now we can test parts of our application that we *load* asynchronously with system.js.
现在我们可以测试应用程序中的各个部分我们可以用system.js来异步*加载*它们。
What about testing parts that *are themselves asynchronous*? What about testing parts that *are themselves asynchronous*?
如果这些要测试的部分*本身就是异步的*呢?
Let's test a service with a public asynchronous method that fetches heroes from a remote server. Let's test a service with a public asynchronous method that fetches heroes from a remote server.
我们来测试一个带有异步方法的服务,它会从远端服务器中获取英雄列表。