Writing JS tests with fun using Jasmine

Today I’ll talk about JavaScript tests using a cool testing framework: Jasmine.

I’ve been talking about unit tests, acceptance tests, and now I’ll show how you can test your JS code. Jasmine is more than a test framework. It’s more related with BDD because it provides a fluent API that can be understood as scenarios/steps and also improve our code design as consequence.

Well, lets start!

First, we have to set up our test environment. As the main subject of this post is to demonstrate tests working, I’ll just share the set up link, and you can see how to do this. Don’t be scared! It’s easy!

For this example I chose to implement the Euler Number(e) using Taylor Series and Factorial function using JavaScript approach.

(1) According to the definitions we have to implement the Factorial function first. Using TDD at the this time is a good choice, because probably we are not sure enough about the behavior of this function and the framework.

So, we define our Factorial spec as follows:

describe("Factorial function", function() {

	beforeEach(function() {
	    factorial = new Factorial();
	 });

	it("should calculate 1!", function() {
		expect(factorial.calculate(1)).toEqual(1);
	});
});

The beforeEach function is responsible to setup our tests. In this case we just initialise factorial variable.

And the it function contain code to the execute the tests. In the example above we expect that 1! returns the value 1.

Next we code the Factorial Object including calculate function with a simple return to let the test pass.

function Factorial() {
}

Factorial.prototype.calculate = function(n) {
	  return 1;
};

first-result

 

After see our test pass, we can add one more test (to compute 2!) and run

it("should calculate 2!", function() {
	expect(factorial.calculate(2)).toEqual(2);
})

 

Now, we can see this error:
first-error

 

Let’s look at the factorial algorithm:


factorial(n):
             = 1, if n = 0;
             = n * fatorial(n-1), if n > 0;
             undefined, otherwise

 

Moving fast and implementing calculate function:

function Factorial() {

}

Factorial.prototype.calculate = function(n) {
	if(n < 0) {
		return undefined;
	} else {
		if(n === 0 || n === 1) {
			return 1;
		}
	}
	return n*arguments.callee(n-1);
};

 

Wait, don’t forget to include more tests to compute 3!, 4!, 5! and 10! for example:

describe("Factorial function", function() {

	beforeEach(function() {
	    factorial = new Factorial();
	 });

	it("should calculate 1!", function() {
		expect(factorial.calculate(1)).toEqual(1);
	});

	it("should calculate 2!", function() {
		expect(factorial.calculate(2)).toEqual(2);
	});

	it("should calculate 3!";, function() {
		expect(factorial.calculate(3)).toEqual(6);
	});

	it("should calculate 5!", function() {
		expect(factorial.calculate(5)).toEqual(120);
	});

	it("should calculate 10!", function() {
		expect(factorial.calculate(10)).toEqual(3628800);
	});

	it("should return undefined for negative numbers!", function() {
		expect(factorial.calculate(-1)).toBeUndefined();
	});
});

 

Running the tests one more time:
factorial-complete

And if we doing it well.. Success! 🙂

 

(2) Now, we can implement the taylor series algorithm using our factorial.calculate function.
The Taylor series to compute Euler Number is defined by:

e = 1 + 1/1! + 1/2! + 1/3! + 1/4! + …

So we have our function to find series for any number. If we pass large numbers, the Taylor series will converge to a value close to the e number.

function TaylorSeries() {

}

TaylorSeries.prototype.find = function(n) {
	var e = 1;
	var factorial = new Factorial();
	if(n <= 0) {
		return 0;
	} else {
		for(var i = 1; i < n; i++) {
			e = e + ( 1/factorial.calculate(i) );
		}
	}
	return e;
};

 

To see the behavior of Taylor series we can add some tests to find function:

describe("Taylor series", function() {

	beforeEach(function() {
	    taylorSeries = new TaylorSeries();
	 });

	it("should return zero for negative series", function() {
		expect(taylorSeries.find(-1)).toEqual(0);
	});

	it("should return zero for zero series", function() {
		expect(taylorSeries.find(0)).toEqual(0);
	});

	it("should return taylor series for one", function() {
		expect(taylorSeries.find(1)).toEqual(1);
	});

	it("should return taylor series for two", function() {
		expect(taylorSeries.find(2)).toEqual(2);
	});

	it("should return taylor series for three", function() {
		expect(taylorSeries.find(3)).toEqual(2.5);
	});

	it("should return taylor series for four", function() {
		expect(taylorSeries.find(4)).toBeCloseTo(2.66, 1);
	});

});

 

And finally we have this output of SpecRunner running all tests:
specs-completes

Really nice, huh? 😀

Jasmine is a powerful tool. This example is pretty simple, but if you are using any JavaScript framework like AngularJS, Knockout, among others, Jasmine can work very well and help you to cover your server-side code and provide a quick feedback.

And keep in mind: Don’t forget the tests!

Anúncios

2 comentários em “Writing JS tests with fun using Jasmine”

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s