Tutorial: Developing an angular app driven by tests
Tags: angular, tdd, jasmine, webdev
Published: 2018-07-31 08:00:49

---
title: Tutorial: Developing an angular app driven by tests
published: true
tags: Angular,TDD,jasmine,tdd,webdev
canonical_url: 
cover_image: https://i0.wp.com/maimart.de/wp-content/uploads/2018/07/TDD__Angular.png?w=1280
---
This article is a tutorial for developing Angular applications driven by tests (TDD).

## Introduction

For a long time graphical user interfaces of complex systems were made of solid and heavy weighted technologies of higher developed, object oriented programming languages.

Mostly UIs have been fat clients, developed with WPF or Swing. Just rarely they were thin clients as web applications.

And even in this seldom cases, HTML and JavaScript got abstracted by big frameworks like ASP or JSF and rendered on server side.

But the language core of JavaScript evolved well with ECMAScript 2015 and so got interesting for more complex applications, too.

Based on the suggestions to ECMAScript2015, TypeScript raised and became an additional option to build web applications on a very high language level that even types statically.

This big language improvements and the strong support of giants like Facebook and Google made web technologies to get more and more interesting for developing more complex applications as single page applications (SPA).

Unfortunately the source code of web applications still has the bad record to be on a lower quality level when regarding readability, design and test coverage.

But the value of creating high quality code, for sustainable further development and maintenance, is independent of the technology and so are the methodologies that ensures that value.

Test driven development (TDD) is a methodology of the Extreme Programming (XP) to develop high quality and well tested code.

In TDD we first specify and validate the behavior in tests, before we start to implement it. When the tests succeeds, we refactor the code to improve the readability and structure of the code.

This leads to well testable and tested code and a process where developers early have to think about the structure, respectively the design of the code.

By specifying functionality in tests first,  we effectively only develop functionality that is required and preserves against developing predictive and unnecessary complex code.

Projects created with the Angular CLI, out of the box contains all tools we need to develop driven by tests.

This tutorial bases on a simple scenario and describes how to develop Angular project driven by tests.

## The scenario

We want to focus the methodology and so choose a very simple scenario.

The application is a very lightweight contact management tool and provides only two functionalities:

- displaying contacts
- adding new contacts

## Setup the Angular project

We first create an Angualr project with the Angular CLI.
`ng new ContactManager`

We want to start from the scratch, so we:

- delete the component _app.component_
- cleanup dependents _app.module_ und _index.html_
- delete the end-to-end specifications in the directory _e2e/src_
- and check our changes by building the project with `ng build`

## The „Walking Skeleton“

Our system is very small, does not communicate with any backend and for the sake of convenience it is not deployed automatically.

So in our case the walking skeleton is a crosscut for developing our application driven by tests.

This should contain an e2e-test that interacts with the web application by page objects and a first small component which is developed driven by tests.

A suitable first small story to build the walking skeleton is to display the contacts.

## Approach

We develop in short TDD iterations.

I am using some special text styles to get the tutorial more readable and clear:

*First we talk about and specify what we want to achieve in the next tdd 
iteration. In best case we don´t develop for our own, but have paired with 
another developer.*

**_Test fails!_** We specify an accordingly test, start it and watch it fail.

**_Test succeeds!_** After that we implement the functionality and start the test again until it succeeds.

We check our code style, make some refactorings and after that we start with the next small tdd iteration.

## Specifying the story in a first e2e-test

We specify the context of the “contact management” in a new e2e-specification /e2e/src/c_ontact-management.e2e-spec.ts_.

*We define, that the contact management initially lists the two contacts “Max” and “Moritz”.*

Within the e2e-test we want to interact with the application on a very high level and delegate the access to the HTML-Elements to so called “page objects”.

In TDD manner, we write the e2e-test, as if there would already exist a class _ContactManagementPage _and so define it in the most meaningful way from the clients point of view.

We create an instance of the _ContactManagementPage_, navigate to its view and verify that the contacts “Max” and “Moritz” are listed.

```javascript
describe('Contact Management', function () {

  it('should show a list of contacts, initially containing "Max" and "Moritz"', function () {
    const page: ContactManagementPage = new ContactManagementPage();
    page.navigateTo();
    expect(page.shownNamesOfContacts()).toContain('Max');
    expect(page.shownNamesOfContacts()).toContain('Moritz');
  });
});
```

When finished, we create the class _ContactManagementPage_ _/e2e/src/pageobjects/contact-management.po.ts,_ as assumed in the e2e-test.

**_Test fails!_** Now the test compiles, but fails as expected.

We start implementing the page object´s _navigateTo_-method, which navigates to the contact management view. In our case it is the root content “/”.

Next we need the names of all listed contacts. At this point, we define that the view contains HTML-elements of the class _“contact”,_ which again contains elements of the class _“name”_.

We implement _#shownNamesOfContacts_ by getting these elements and map their text values.

Protractor works asynchronous with its own _Promise_ class. We have to make sure to import and use the right  _Promise_-Class of the Protractor library.

```javascript
import {browser, by, element, ElementArrayFinder, ElementFinder, promise} from 'protractor';
import Promise = promise.Promise;

export class ContactManagementPage {
  navigateTo() {
    browser.get('/');
  }

  shownNamesOfContacts(): Promise<string[]> {
    return this.contactNameItems().map(contactNameItem => contactNameItem.getText());
  }

  private contactNameItems(): ElementArrayFinder {
    return element.all(by.css('.contact .name'));
  }
}
```

**_Test fails!_** The test fails with the hint that no Angular application could be found. Currently no angular component gets bootstrapped.

*To fix that issue we next create an Angular component “_contact-list_” with the Angular CLI.*

`ng generate component contact-list`

It is automatically assigned to the global a_pp-module_ and declared within it. So far that´s ok for this tutorial, but we also have to integrate the component in our _index.html_ and configure our  module to bootstrap the component.

**_Test fails!_** The e2e-test still fails, but this time as intended by not fulfilling the expectations of the test.

## Implementing the component

*First the component should display a list of items per contact.*

We create a test case in the _contact-list.component.spec_ which was generated by the Angular CLI. While writing it, we again assume all dependencies already exist.

```javascript
it('should display an element for each contact', function () {
  component.contacts = [new Contact('DummyContact'), new Contact('DummyContact2')];
  fixture.detectChanges();

  const contactElements: NodeList = fixture.nativeElement.querySelectorAll('.contact');

  expect(contactElements.length).toBe(2);
});
```

The code does not compile. We need a data structure „_Contact_“ and a property „_contacts“_ in the component´s controller _contact-list.components.ts_ which provides the contacts_._

We create the class Klasse _/model/contact.ts_

```javascript
export class Contact {
  constructor(public name: string) {
  }
}
```

and extend the controller by the property `contacts: Contact[]`.

**_Test fails!_** This time we start the karma test server and runner with `ng test`and watch the written test failing, because we expect two contact elements that are currently no displayed.

We keep karma running and so get instant feedback about our changes and their impact on the behavior.

To display an item for each contact, we extend the view _contact-list.component.html_.

```html
<div>
  <ul>
    <li *ngFor="let contact of contacts" class="contact"></li>
  </ul>
</div>
```

**_Test succeeds!_** The test succeeds!

*So far, now we want to display the contact´s names.*

```javascript
it('a contact element should display the contact´s name', function () {
  const contact = new Contact('SomeName');
  component.contacts = [contact];

  fixture.detectChanges();

  const nameElement: HTMLElement = fixture.nativeElement.querySelector('.contact .name');
  expect(nameElement).not.toBeNull();
  expect(nameElement.textContent).toEqual(contact.name);
});
```

**_Test fails!_** As expected the test fails.

*We make the list to display the name.*

```html
<div>
  <ul>
    <li *ngFor="let contact of contacts" class="contact">
      <span class="name">{{contact.name}}</span>
    </li>
  </ul>
</div>
```

**_Test succeeds!_** Our component now displays the contact´s names.

Are we finished? We have a look at the e2e-tests.

**_Test fails!_** They still fail. We expect “Max” and “Moritz” to be listed initially.

*We want our component to initially contain the contacts “Max” and “Moritz”.*

```javascript
it('should initially display the contacts "Max" and "Moritz"', function () {
  const nameElements: NodeList = fixture.nativeElement.querySelectorAll('.contact .name');
  const names: string[]  = Array.from(nameElements, nameElement => nameElement.textContent);
  expect(names).toContain("Max");
  expect(names).toContain("Moritz");
});
```

**_Test fails!_** Now we also have a failing component test.

We initialize the controller´s contact-property with that contacts.

**_Test succeeds!_** All component tests succeeds!

**_Test succeeds!_** Now the e2e-test is also green and the implementation of the story is done!

> Contact Management  
> √ should show a list of contacts, initially containing “Max” and “Moritz”

## Further development

Now our skeleton walks and we can continue with further development.

Possible next steps could be:

- Refactoring: Extraction and delegation of the contact-list-specific content to its own page object to keep the contact-page-object clean and to reuse it in other tests.
- Story: Creation of new contacts
  - Creating a new contact by entering its name in a textfield followed by pressing the enter-button
  - when a new contact is created, the textfield should be cleared
- Optimization: Managing the data in a Redux-store

## Conclusion

Frameworks like Jasmine, Karma or Protractor support test driven development of web applications very well.

In case of Angular, projects created by the Angular CLI are already preconfigured with Jasmin, Karma and Protractor and out of the box can be developed driven by tests.

So TDD is also for web applications a very good methodology to create tested and well designed source code on a very high quality level.

In combination with other methodologies like pair programming and clean coding, nice synergy effect arise to develop and maintain complex applications in an effective and efficient way.

 

See also [Test strategies when developing redux stores in angular apps driven by tests](http://maimart.de/test-strategies-when-developing-redux-stores-in-angular-apps-driven-by-tests) and [Pushing an angular project to the aws cloud](http://maimart.de/pushing-an-angular-project-to-the-aws-cloud)

The post [Tutorial: Developing an angular app driven by tests](http://maimart.de/developing-an-angular-app-driven-by-tests) appeared first on [maimArt](http://maimart.de).