Blogger news

Blogger templates

Monday, July 28, 2014

Testing JavaScript code with Jasmine

Jasmine is a behavior-driven testing framework for JavaScript programming language.
To set-up Jasmine is very easy. Download latest release folder of Jasmine, unzip it and add in your project. Structure of Jasmine will be as below,


When you open SpecRunner.html in browser, you will see something like below,

I am going to explain Jasmine syntax with a simple calculator example. So let's start


We are proceeding with TDD approach mean first we will write test, make it fail then write code, make test green and refactor code.

Step 1 :- Add a JS file called CalculatorSpec.js
First we have have a give a description in CalculatorSpec.js about our test and the syntax will be as below,
describe("Calculator", function () {

});

describe("Calculator"… is what is called a suite. The name of the suite (“Calculator” in this case) typically defines a component of your application; this could be a class, a function, or maybe something else.

In Jasmine we can write nested description (suite). Say Calculator is our main test but we want to create seperate section for addition then our spec will be as below. See the highlighted block

describe("Calculator", function () {

    describe("Addition", function () {

    })
});

So our addition description is ready now we should tell what it should do. Say it should add two numbers then out spec will be like below,
describe("Calculator", function () {

    describe("Addition", function () {

        it("Should return 12 when I pass 7 and 5", function () {

        });

    })

});

Inside of that suite (technically, inside of an anonymous function), is the it() block.
This is called a specification, or a spec for short. It’s a JavaScript function that says what
some small piece of your component should do. It says it in plain English (“Addition”)
and in code.

Our Spec is ready now and now we have compare expected result with actual result. So I am modifying CalculatorSpec.js as below,

describe("Calculator", function () {

    describe("Addition", function () {
        it("Should return 12 when I pass 7 and 5", function () {

            expect(Add(7, 5)).toBe(12);

        });
    })

});

If you look at the highlighted area we are calling a function 'Add' inside expect method and comparing the result. Here expected result should be 12.  'toBe' is called matcher in Jasmine. You will get list of matchers here.

Add reference of CalculatorSpec.js to SpecRunner.html (delete the default reference of PlayerSpec.js as we dont want that now) and browse SpecRunner.html. You will get below error,



See the error in red box "ReferenceError: Add is not defined". Yes you are right we don't have an Add function any where so we failed the test and that is what we wanted as we are doing TDD. Remember the slongan of TDD, "RED GREEN REFACTOR". So successfully passed first step of Tdd, RED.
Next we want to make test green for that we should obviously add the missing Add function. So I am creating a js file called Calculator.js and add the below function in it,

     function Add(a, b) {
          return a + b;
       }

Add the reference of Calculator.js in SpecRunner.html and browse SpecRunner.html again. Now you will get below screen,

Yes your test is GREEN now means your test passed. So you passed the second step of Tdd, GREEN. Next is REFACTORING. I refactored Calculator.js as below,

var Calculator = function () {
    
    this.Add = function (firstNumber , secondNumber) {
        return firstNumber + secondNumber;
    };
}

Well I created a constructor function 'Calculator' and if you browse SpecRunner.html you will get below screen,

Again we got the same error 
"ReferenceError: Add is not defined". Why? What happened? Well  Add is now based on the object of 'Calculator', means we have to create object of calculator to access 'Add' method. So let's do that in CalculatorSpec.js. I modified CalculatorSpec.js as below,
describe("Calculator", function () {

    describe("Addition", function () {
         var calculator = new Calculator();
        it("Should return 12 when I pass 7 and 5", function () {            
            expect(calculator.Add(7,5)).toBe(12);

        });
    })
});

Now browse SpecRunner.html and you can find your test passed again. Well have have achieved third step of Tdd, REFACTOR.

Assume that you have separate suite for other functionalities like  subtraction, multiplication and division. So we have to create Calculator object each time and that is bad way of coding and violation of DRY principle. What we will do? Well this is the best time to introduce 'beforeeach' and 'aftereach'. In usual Tdd terminology it is equivalent to Setup and Teardown.

I am going to modify CalculatorSpec.js as below,
describe("Calculator", function () {
    var calculator;

    beforeEach(function () {
        calculator = new Calculator();
    });

    describe("Addition", function () {
        it("Should return 12 when I pass 7 and 5", function () {
            expect(calculator.Add(7, 5)).toBe(12);

        });
    })

    afterEach(function () {
        calculator = null;
    });
});

See the highlighted area. 'beforeEach' and 'afterEach' will run only once for the suite 'Calculator'. If I need to add separate suite for other functionalities I don't want to instantiate calculator object again as it is already instantiated in before each. After all test run 'afterEach' will call and it makes calculator object to be null. 

I am leaving it to you to add remaining tests and  code of calculator as it will be exactly same as we did for addition.

You can read more about Jasmine here

No comments:

Post a Comment