Skip to content
Jhonatan Core edited this page May 30, 2016 · 6 revisions

Test-Driven Development

Introduction

Test-driven development (TDD) is a software development process that relies on another two practices: Test Fist Develop and Refactoring.

When we work with this methodology we base on the repetition of a very short development cycle. The requirements are turned into very specific test cases, then the software is improved to pass the new tests, only. This is opposed to software development that allows software to be added that isn’t proven to meet requirements. The next step is refactoring the code.

The goal is get a clean code that works. The idea is translate the tests, with this, when the test are passed we have a software that satisfy the requirements.

Benefits

TODO

Limitations

The Test-driven development require that the test can be automatized. This is complex in the next fields

  • Graphic User Interfaces (GUIs), although there are some partial solution

  • Distributed object, although the simulated objects (MockObjects) can help us

  • Database (DB). Do test of code that works with a DB is complex because require add some data in the DB and be sure that this data are in the DB in the moment we are testing. Also we need to have a DB that we can modify it freely

TDD in AngularJS2

To test our AngularJS2 applications we are going to use Jasmine and Karma tools

Testing AngularJS2 Components

We need that all tests finish with .spec.ts, this is how we made to tell Karma which files should be executed as tests.

import {it, describe, expect, beforeEach, inject} from 'angular2/testing';
import {MyList} from "./my-list";
import {MyService} from "../services/my-service";

describe('MyList Tests', () => {
    let list:MyList;
    let service:MyService = new MyService();

    beforeEach(() => {
        list = new MyList(service);
    });

    it('Should get 5 dogs', () => {
        list.ngOnInit();

        expect(list.items.length).toBe(5);
        expect(list.items).toEqual(['golden retriever', 'french bulldog', 'german shepherd', 'alaskan husky', 'jack russel terrier']);
    });
});

As you can see the tests are pretty easy to do. Just create a new instance of your Component dependencies, then create a new Component instance with the dependencies required and then you can just start executing functions and expecting results.

If you’re used to testing in Angular 1.X you can see that it looks very similar but even easier and clearer.

Testing AngularJS2 Services

Services are pretty much the same as Components. In this case we need to test a branch, so we made two tests to see if everything works as expected.

import {it, describe, expect, beforeEach, inject} from 'angular2/testing';
import {MyService} from "./my-service";

describe('MyService Tests', () => {
    let service:MyService = new MyService();

    it('Should return a list of dogs', () => {
        var items = service.getDogs(4);

        expect(items).toEqual(['golden retriever', 'french bulldog', 'german shepherd', 'alaskan husky']);
    });

    it('Should get all dogs available', () => {
        var items = service.getDogs(100);

        expect(items).toEqual(['golden retriever', 'french bulldog', 'german shepherd', 'alaskan husky', 'jack russel terrier', 'boxer', 'chow chow', 'pug', 'akita', 'corgi', 'labrador']);
    });
});

Testing AngularJS2 Pipes

import {it, describe, expect, beforeEach, inject} from 'angular2/testing';
import {MyPipe} from "./my-pipe";

describe('MyPipe Tests', () => {
    let pipe:MyPipe;

    beforeEach(() => {
        pipe = new MyPipe();
    });

    it('Should capitalize all words in a string', () => {
        var result = pipe.transform('golden retriever', null);

        expect(result).toEqual('Golden Retriever');
    });
});

As you can see if we take a look to our other tests and compare each other it is indeed very hard to figure out which one is a Component, a Service or a Pipe. That means that tests haves a great separation of concerns.