Angular Testing: A Developer’s Introduction

In this guide, we’ll look at how we can write automated tests in Angular 5 projects. Angular Testing is a core feature available in every project that was set up with either the Angular CLI or the Angular quick start project.

The subject of Angular testing is vast, as it’s a complex and very involved topic. It would require several chapters or a full-length course to cover it fully. So in this guide, I’ll show you just the basics to get you started.

Prerequisites

At the time of writing, Angular 5.2 is the current stable version — which is what we’ll be using here. This guide assumes you at least have a solid grasp of Angular 4+ fundamentals. It’s also assumed you at least understand the concept or have some skills writing automated tests.

We’ll base our testing examples on Angular’s official beginner tutorial to demonstrate how to write tests for components and services. You can find the completed code with tests on our GitHub repository. At the end of this guide, you should have the skills to implement several passing tests in Angular 5.

Angular Testing Technologies

As you already know, an Angular project is made up of templates, components, services and modules. They all run inside what’s known as the Angular environment. While it’s possible to write isolated tests, you won’t really know how your code will interact with other elements within the Angular environment.

Luckily, we have several technologies that can help us write such unit tests with the least amount of effort.

1. Angular Testing Utilities

This is a set of classes and functions that are needed to build a test environment for Angular code. You can find them on Angular’s api documentation. The most important of all is the TestBed. It’s used to configure an Angular module just the same way as the @NgModule — except that it prepares the module for testing. It has a configureTestingModule function where you provide all the necessary dependencies for your component to function in a test environment. Here’s an example of the dashboard component being prepared to run in a test environment. Several dependencies are needed by this component for the test to run:

TestBed.configureTestingModule({
  imports: [ RouterTestingModule ],
  declarations: [ DashboardComponent ],
  schemas: [ NO_ERRORS_SCHEMA ],
  providers: [
    {
      provide: HeroService,
      useClass: MockHeroService
    }
  ],
})
.compileComponents();

We’ll look more closely at what’s going on here a little further below.

2. Jasmine

Jasmine is the de facto framework for writing Angular tests. Basically, it’s a testing framework that uses the behavior-driven notation. Writing a test in Jasmine is quite simple:

describe('createCustomer' () => {

  it('should create new customer',(customer) => {
    ...
    expect(response).toEqual(newCustomer)
  });

  it('should not create customer with missing fields', () => {
    ...
    expect(response.error.message).toEqual('missing parameters')
  });

  it('should not create customer with existing record', () => {
    ...
    expect(response.error.message).toEqual('record already exists')
  });
});

The anatomy of a Jasmine test is made up of at least two elements: a describe function, which is a suite of tests, and an it function, which is the test itself. We normally use describe to indicate the function we’re focusing on — for example, createCustomer(). Then, within the suite, we create multiple it tests. Each test puts the target function under a different condition in order to ensure it behaves as expected. You can refer to the Jasmine docs for more information.

3. Karma

Karma is a tool for executing source code against test code inside a browser environment. It supports the running of tests in each browser it’s configured for. Results are displayed on both the command line and on the browser for the developer to inspect which tests have passed or failed. Karma also watches the files and can trigger a test rerun whenever a file changes. At the root of the Angular project, we have the file karma.conf that’s used to configure Karma. The contents should look something like this:

module.exports = function (config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine', '@angular/cli'],
    plugins: [
      require('karma-jasmine'),
      require('karma-chrome-launcher'),
      require('karma-jasmine-html-reporter'),
      require('karma-coverage-istanbul-reporter'),
      require('@angular/cli/plugins/karma')
    ],
    client:{
      clearContext: false // leave Jasmine Spec Runner output visible in browser
    },
    coverageIstanbulReporter: {
      reports: [ 'html', 'lcovonly' ],
      fixWebpackSourcePaths: true
    },
    angularCli: {
      environment: 'dev'
    },
    reporters: ['progress', 'kjhtml'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['Chrome'],
    singleRun: false
  });
};

Do check out Karma’s configuration documentation to learn how to customize it. As you can see, Chrome is listed as the browser to use for running tests. You’ll need to define an environment variable called CHROME_BIN that points to the location of your Chrome browser executable. If you’re using Linux, just add this line to your .bashrc file:

export CHROME_BIN="/usr/bin/chromium-browser"

In order for Karma to run your tests, you must ensure the test files end with .spec.ts. You should note that Karma was designed to mostly run unit tests. To run end-to-end tests, we’ll need another tool, Protractor, which we’ll look into next.

4. Protractor

Protractor is an end-to-end test framework for Angular. It runs your tests inside a real browser, interacting with it as real person would. Unlike unit tests, where we test individual functions, here we test the entire logic. Protractor is able to fill in forms, click buttons and confirm that the expected data and styling is displayed in the HTML document. Just like Karma, Protractor has its own configuration file at the root of your Angular project, protractor.conf:

const { SpecReporter } = require('jasmine-spec-reporter');

exports.config = {
  allScriptsTimeout: 11000,
  specs: [
    './e2e/**/*.e2e-spec.ts'
  ],
  capabilities: {
    'browserName': 'chrome'
  },
  directConnect: true,
  baseUrl: 'http://localhost:4200/',
  framework: 'jasmine',
  jasmineNodeOpts: {
    showColors: true,
    defaultTimeoutInterval: 30000,
    print: function() {}
  },
  onPrepare() {
    require('ts-node').register({
      project: 'e2e/tsconfig.e2e.json'
    });
    jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
  }
};

You can find the documentation for its configuration here. Unlike Jasmine/Karma tests, Protractor tests are located outside the src folder, in a folder called e2e. We’ll look into writing end-to-end tests later down the road. For now, let’s start writing unit tests.

Continue reading %Angular Testing: A Developer’s Introduction%

Powered by WPeMatico