Sunday, 2 April 2017

Configuring code coverage with Karma ,jasmine and Angular 2

What is code coverage ?


As the good ol google says "In computer science, code coverage is a measure used to describe the degree to which the source code of a program is executed when a particular test suite runs." ,simple as it is ;)


How do we do it ?


Ingredients
1.Basic knowledge of Angular 2
2,Typescript (if you are coding in type script)
3.Npm
4.Karma Jasmine

and finally some good googling skills ;)

Step 1 : Scaffold your Angular 2 Application ,Install all the necessary packages that comes along with the package.json
In a npm console ,

ng new covereageexample

Navigate inside the folder and do

npm install

finally after installation ,check the application is running by

ng serve

Now lets configure the ingredients needed for code coverage
1.karma typescript

Run unit tests written in Typescript with full type checking, seamlessly without extra build steps or scripts.
https://www.npmjs.com/package/karma-typescript

2.karma-typescript-angular-transform

This plugin rewrites relative urls in the templateUrl and styleUrls properties of Angular2 components, making sure that the Angular framework can resolve the urls when running tests with karma-typescript
https://www.npmjs.com/package/karma-typescript-angular2-transform

3.karma-html-reporter
This plugin will generates a HTML report of all the test cases in the application
https://www.npmjs.com/package/karma-html-reporter

Add these packages in your package.json and do npm install (I will share the entire code at the end of this blog ;))

The karma.config file

module.exports = function(config) {
    config.set({
        //import the frameworks
        frameworks: ["jasmine""karma-typescript"],
        //base.spec.ts is the file which bootstraps the testing
        //sr/app ... will contain our code
        files: [
            { pattern: "base.spec.ts" },
            { pattern: "src/app/**/*.+(ts|html)" }
        ],
        //preprocessor will allow us to do some work before serving it to the  //browser
//http://karma-runner.github.io/1.0/config/preprocessors.html
        preprocessors: {
            "**/*.ts": ["karma-typescript"]
        },
       
        karmaTypescriptConfig: {
            bundlerOptions: {
                entrypoints: /\.spec\.ts$/,
//transform plugin for relative urls (styleUrl and tetmplateUrl)
                transforms: [
                    require("karma-typescript-angular2-transform")
                ]
            },
//coverage reports will be generated in the `coverage` folder on the root level
            coverageOptions: {
                instrumentation: true,
              
            }
        },
//generation of HTML reports
         htmlReporter: { 
//directory ,report will get generated inside folder `testcases` in the root folder
         outputDir: 'testcases',
   
         },
         //progress - for running the test case
         //karma-type-script - for code coverage
         //html - generation of HTML reports of test cases
        reporters: ["progress""karma-typescript","html"],
      
        browsers: ["Chrome"]
    });
};


This is my Hellocomponent.ts look like

import { Component } from "@angular/core";

@Component({
    selector: "app-hello",
    styleUrls: ["../assets/style/main.css"],
    templateUrl: "hello.html"
})
export class HelloComponent {
    public title = "Hello :)";
   
}


And my hellocomponent.spec.ts will look like this


import { DebugElement } from "@angular/core";
import { asyncComponentFixtureTestBed } from "@angular/core/testing";
import { By } from "@angular/platform-browser";

import { HelloComponent } from "./hello";

describe("HelloComponent", () => {

    let fixtureComponentFixture<HelloComponent>;

    beforeEach(async(() => {

        return TestBed
            .configureTestingModule({
                declarations: [HelloComponent]
            })
            .compileComponents()
            .then(() => {
                fixture = TestBed.createComponent(HelloComponent);
            });
    }));

    it("should display original title", () => {
        let debugElement = fixture.debugElement.query(By.css("h1"));
        fixture.detectChanges();
        expect(debugElement.nativeElement.textContent).toEqual("Hello :)");
    });

    it("should display a different test title", () => {
        let debugElement = fixture.debugElement.query(By.css("h1"));
        fixture.componentInstance.title = "Test Title";
        fixture.detectChanges();
        expect(debugElement.nativeElement.textContent).toEqual("Test Title");
    });
});


And my hello.html

<h1>{{title}}</h1>


So i have two test cases written which covers all the functionality in hellocomponent ,
The coverage report will look like above ,its 100% covered

Clicking on hello.ts will show our code ,what is covered and not covered

Now lets check our covereage functionality really works or not add some code in Hello.ts

import { Component } from "@angular/core";

@Component({
    selector: "app-hello",
    styleUrls: ["../assets/style/main.css"],
    templateUrl: "hello.html"
})
export class HelloComponent {
    public title = "Hello :)";
    //i have added this piece of code and no test cases written yet,
    foo() {
       return 'bar';
    }
}


Lets generate a code covereage again by running npm test,coverage is now only 88.89%














If we click on the hello.ts file  we can see the test cases for the function `foo` is not written ,so  we have to write test cases for foo function.An ideal code coverage for any project will be around 75 to 80%

So that's it guys , ill be covering more on the jasmine test cases in my next post

You can find the entire files and code in the below link

https://www.dropbox.com/s/bao8rgqjj6iefjw/angular2.zip?dl=0





Configuring code coverage with Karma ,jasmine and Angular 2

What is code coverage ? As the good ol google says " In computer science, code coverage is a measure used to describe the degree to...