include ../../../../_includes/_util-fns :markdown 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 don’t always like *making* tests. It’s 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 you’ll 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") :markdown
Pure unit test We test the part in isolation. Either the part has no dependencies or we fake all of its dependencies during the test.
Close-in integration We test a part as it collaborates with closely related parts and/or with the Angular framework. We may fake some of its dependencies.
High level integration 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.
Cross network integration 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.
End-to-End (E2E) 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.
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. It’s 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 can’t 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 didn’t 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. We’ll 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. We’ll learn a number of tips and tricks along the way, including: * what’s worth testing and what isn’t * 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 Here is what we’ll 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 It’s 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 :markdown 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 npm, gulp, and live-server. :markdown Let’s get started!