CHAPTER 1
Angular is a powerful framework for developing component-based web applications. In this book, we are going to focus on the tools and options for improving the quality of your Angular code base. There are several features that can be utilized to produce higher-quality, more-maintainable code.
Lint checking is a static analysis process that reviews your source code files to look for things like patterns and style issues that are present in your source. None of the code in your source files is executed; a set of patterns and rules is simply checked against the source code files. This type of checking won’t detect runtime bugs per se, but will identify areas of the code that might cause unexpected behaviors.
Most lint checkers operate using a set of rules and allow you to customize the rules to your (and your team’s) programming preferences. You can install lint checkers into most code editors to lint check during coding, or you can run lint checking as a separate process after saving your code.
Unit testing creates an instance of your component or service and runs the created instance, checking that your code works as expected. For example, if a component validates birth dates, you could have unit tests to ensure a valid date is provided, and that the date is in the past. Your tests should generally test both good, expected behavior and error conditions. The Angular CLI will generate a basic unit test file when you create a new project and/or new components and services.
Some advantages of unit testing are that errors are found earlier in the development cycle, and unit tests can be used for regression testing (confirming new code doesn’t break previously working code). However, thorough unit testing can take significant time to write. Each Boolean condition would require two tests (one for the IF and another for the ELSE condition).
End-to-end (E2E) testing integrates your components and the browser to provide an automated set of tests mimicking how a user will interact with your system. For example, an E2E test on a login process might open the browser, try to log in with invalid credentials, and confirm that an error message is displayed. Another test within the E2E process would confirm that logging in with valid credentials brings up the application splash screen or main panel.
Each process has a place in your development cycle and should be standard operating practice for Angular development.
Lint checking should always be performed first; it is quick and identifies potential code and style issues. The process is easily customizable, so you can define coding styles and standards that all members on the development team can adhere to.
Unit testing is generally quick to execute, ensuring the methods in your components do what they are expected to do. Unit tests are generally small and run quickly, and should be performed as each component is written or updated. However, unit tests test components in isolation, and don’t check how the components will interact with each other.
End-to-end testing can be very slow, basically running the integrated application within a browser to ensure the components interact with each other and the application UI performs as expected.
While end-to-end testing is a good final, automated test feature, it still does not replace the need for manual, human testing.
If you’ve used the Angular CLI to create a basic project, you will find that the configuration and setup work for lint checking, unit testing, and end-to-end testing is started for you.
This file will be found in the project root and contains a basic set of rules (using presets) and some overwritten rules to tweak the code for Angular modules. Within the node_modules folder, there is a directory called tslint. This folder contains the actual tslint program and library.
For each component created by the CLI, a .spec file with the same base component file name will be generated. You will typically see four files per component: a style sheet, the HTML template code, the component, and the specification file. Code Listing 1 shows a simple component.
Code Listing 1: Basic Angular component
import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'TestProject'; } |
The matching .spec file is shown in Listing 2, and we will cover the file in detail in Chapter 4. You can see the it() method with a text string to indicate what is being tested. These are very simple, basic tests, and you’ll need to keep the file up to date as you build out your component.
Code Listing 2: Basic Angular test component
import { Component } from '@angular/core'; import { TestBed, async } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; import { AppComponent } from './app.component'; describe('AppComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ imports: [ RouterTestingModule ], declarations: [ AppComponent ], }).compileComponents(); })); it('should create the app', () => { const fixture = TestBed.createComponent(AppComponent); const app = fixture.debugElement.componentInstance; expect(app).toBeTruthy(); }); it(`should have as title 'TestProject'`, () => { const fixture = TestBed.createComponent(AppComponent); const app = fixture.debugElement.componentInstance; expect(app.title).toEqual('TestProject'); }); it('should render title', () => { const fixture = TestBed.createComponent(AppComponent); fixture.detectChanges(); const compiled = fixture.debugElement.nativeElement; expect(compiled.querySelector('.content span').textContent). toContain('TestProject app is running!'); }); }); |
In general, the method provides a description of the test and a function to perform the actual test. The expect function indicates the expected result if the test is successful.
The E2E folder contains two files: the protractor.config.js file, which configures the Protractor tool to run the tests; and a tsconfig.json file, which extends the base tsConfig and customizes the compiler options necessary for running the E2E tests.
The src folder within the E2E directory contains two files that are used to drive the E2E test process. The app.po.ts file contains a class representing the application and a few methods to perform operations within the browser. The app.e2e-specs.ts file is the actual TypeScript code that imports the application class from the app.po.ts file, and some classes from Protractor.
The syntax in the E2E file looks at the unit tests, describes the test as a string, and provides a function to perform the actual test. The expect method indicates whether the tests have succeeded.
Much of the test environment is set up for you when you use the Angular CLI. In the remainder of the book, we are going to focus on how use the lint checker, run the unit tests, and perform the end-to-end testing of the entire application. You can build an Angular application and never use these testing options; however, the benefits and confidence of automated testing processes should encourage you to make these tools part of your standard development life cycle.