angular-cn/public/docs/ts/latest/testing/index.jade

124 lines
7.0 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

include ../../../../_includes/_util-fns
:marked
We write **unit tests** to explore and confirm the **behavior** of parts of our application.
We like *having* unit tests for many reasons, three of them in particular:
1. They **guard** against breaking existing code (“regressions”) when we make changes.
1. They **clarify** what the code does both when used as intended and when faced with deviant conditions.
1. They **reveal** mistakes in design and implementation. Tests force us to look at our code from many angles. When a part of our application seems hard to test, we may have discovered a design flaw, something we can cure now rather than later when it becomes expensive to fix.
While we like *having* tests, we dont always like *making* tests. Its a bit like the difference between *having* money (yeah!) and *making* money (oof!).
Our lofty goal in this chapter is make it easy for you to write Angular application tests. If that goal exceeds our reach, we can at least make testing *easier*… and easy enough that youll want to write tests for your application.
## The Testing Spectrum
Exploring behavior with tests is called “Functional Testing”. There are other important forms of testing too such as acceptance, security, performance, and deployment testing. We concentrate on functional testing in this section on unit testing.
There is considerable variety within functional testing, a spectrum from short, quick pure unit tests to long running end-to-end tests. We could classify them in broad groups
figure.image-display
img(src='/resources/images/devguide/unit-testing/spectrum.png' alt="Functional Testing Spectrum")
:marked
<table style="box-shadow: none">
<tr>
<td style="border-bottom: none">Pure unit test</td>
<td style="border-bottom: none; width: 80%">We test the part in isolation. Either the part has no dependencies or we fake all of its dependencies during the test.</td>
</tr>
<tr>
<td style="border-bottom: none">Close-in integration</td>
<td style="border-bottom: none">We test a part as it collaborates with closely related parts and/or with the Angular framework. We may fake some of its dependencies.</td>
</tr>
<tr>
<td style="border-bottom: none">High level integration</td>
<td style="border-bottom: none">We test a part as it interacts with many, wide-ranging aspects of the system including the browser DOM. Such tests are often asynchronous which means the test runner must pause until the entire tested sequence completes.</td>
</tr>
<tr>
<td style="border-bottom: none">Cross network integration</td>
<td style="border-bottom: none">A more demanding “high level integration” test that reaches across the network boundary to touch a test server such as tests of a data service that exercise both client and server components.</td>
</tr>
<tr>
<td style="border-bottom: none">End-to-End (E2E)</td>
<td style="border-bottom: none">We simulate the actions of users as they navigate through the application. Such tests strive to investigate the behavior of the application as a whole, replicating the user experience as faithfully as possible.</td>
</tr>
</table>
Each kind of test has its strengths and weaknesses. The tests to the left are typically easier to write, more focused, more robust, and they often run faster than the tests to the right. Its much easier to create adverse, stressful conditions for a pure unit test than an end-to-end test. We get a lot of value for comparatively little effort. That may be why we will write a lot more unit tests than end-to-end tests.
On the other hand, the shorter tests cant reveal the integration problems that may be hiding at the boundaries within the actual application. We can *simulate* problems that we *imagine* might arise. But we will miss the problems in the real system that we didnt anticipate.
We need the full spectrum of tests to assure the behavioral quality of the entire application.
In this Unit Testing section we learn to write tests in all of these categories *except end-to-end*. We cover **end-to-end** tests in a separate section because they require special tools and considerations.
Well begin on the left side of the spectrum, with pure unit tests of simple parts such as the `Hero` model class and a custom pipe named `InitCapsPipe`. Then we work our way to the right as we explore the more complex parts of our application such as components, the router, and remote data access.
Well learn a number of tips and tricks along the way, including:
* whats worth testing and what isnt
* when a test is telling us to rethink our design
* how to debug our tests
* how to write asynchronous tests
* when to mock and how
## Unit Testing Chapters
<!-- TODO This toc feels out of place here -->
Here is what well learn in the unit testing chapters.
1. Jasmine Testing 101
- setup to run Jasmine tests in the browser
- basic Jasmine testing skills
- write simple Jasmine tests in TypeScript
- debug a test in the browser
1. The Application Under Test
1. Test a class
- test a simple application class outside of Angular
- where to put the test file
- load a test file with systemJS
1. Test a Pipe
- test a simple Angular Pipe class
- add the Angular 2 library to the test harness
- load multiple test files using system.js
1. Test an Asynchronous Service
- test an asynchronous service class outside of Angular
- write a test plan in code
- fake a dependency
- master the `catch(fail).then(done)` pattern
- move setup to `beforeEach`
- test when a dependency fails
- control async test timeout
1. The Angular Test Environment
- the Angular test environment and why we need help
- add the Angular Test libraries to the test harness
- test the same async service using Angular Dependency Injection
- reduce friction with test helpers
- introducing spies
1. Test a Component
- test the component outside of Angular
- mock the dependent asynchronous service
- simulate interaction with the view (no DOM)
- use a spy-promise to control asynchronous test flow
1. Test a Component in the DOM
- test the component inside the Angular test environment
- use the `TestComponentBuilder`
- more test helpers
- interact with the DOM
- bind to a mock dependent asynchronous service
1. Run the tests with karma
Its a big agenda. Fortunately, you can learn a little bit at a time and put each lesson to use.
.callout.is-helpful
header How to Use This Guide
:marked
The Unit Testing chapters build upon each other. We recommend reading them in order.
We're also assuming that you're already comfortable with basic Angular 2 concepts and the tools
we introduced in the [QuickStart](../quickstart.html) and
the [Tour of Heroes](../tutorial/) tutorial
such as <code>npm</code>, <code>gulp</code>, and <code>live-server</code>.
:marked
[Lets get started!](jasmine-testing-101.html)