Jasmine
Developer(s)Pivotal Labs
Initial releaseSeptember 14, 2010; 13 years ago (2010-09-14)[1]
Stable release
2.0
Written inJavaScript
Operating systemCross-platform
TypeUnit Test
LicenseMIT License
Websitehttp://jasmine.github.io/

Jasmine is an open source development framework for testing a JavaScript code. It is run independently and is behavior driven. It doesn’t require any DOM. It is favored because of its clean, easy to read and obvious syntax.[2]

History

edit

The developers at Pivotal Labs for Jasmine previously developed a similar unit testing framework called JsUnit before active development of Jasmine.[3]

Getting Started

edit

Installation

edit

The latest standalone download version is available at https://github.com/jasmine/jasmine [4] The resulting directory has the following structure

 
This is the directory structure of Jasmine standalone version







Folders and their meanings

edit
  • lib - Contains Jasmine Framework files
  • src - Contains the actual Javascript code we want to test
  • spec - Contains the Javascript test code
  • SpecRunner.html - File that runs the tests in the browser

[5]

Key terms

edit
  • Suit : Starts with a global Jasmine function describe, which takes two parameters (Name of the suite as string & spec function)
  • Spec : Function consists of the it block describing the setup code the test needs to do.
  • Matcher : Spec function takes this function as parameter. Matcher compares the result of the code with the expected result.

The spec .js file, which tests the JavaScript code consists of suites of test cases. Basic structure of a spec .js file is as follows:

describe(“Name of Suite”, function() {
   it(“what it does”, function() {
      expect(yourJsFunction()).toEqual(“Your expected result”);
   });
});

Running the test

edit
  • Place the .js file to be tested in the src folder
  • Place the spec file in the spec folder
  • Edit SpecRunner.html and include the file names in the "src" tags
  • Run SpecRunner in browser to see the results


Before & After

edit

If in situations where a few lines of setup code needs to be performed for every test, Jasmine provides beforeEach & afterEach functions which allows to run the setup code before and after each test. It eliminates the pain of writing redundant code for every it call.

Example:

describe("MyObject", function () {
    var obj = new MyObject();

    beforeEach(function () {
        obj.setValue("null");
    });

    it("changes value", function () {
        obj.setValue("xyz");
        expect(obj.getValue()).toEqual("xyz");
    })
    it("adds value", function () {
        obj.addValue("pqr");
        expect(obj.getValue()).toEqual(["null", "pqr"]);
    })
});

In the above example, before each test is run, the value of the object is set to null. This is to ensure every test starts with a fresh copy of the object without the previous values persisting.

Matchers

edit

Predefined Matchers (v.2.3.4)

edit

[6]

  • 'toBe'
  • 'toBeCloseTo'
  • 'toBeDefined'
  • 'toBeFalsy'
  • 'toBeGreaterThan',
  • 'toBeLessThan'
  • 'toBeNaN'
  • 'toBeNull'
  • 'toBeTruthy'
  • 'toBeUndefined'
  • 'toContain'
  • 'toEqual'
  • 'toHaveBeenCalled'
  • 'toHaveBeenCalledWith'
  • 'toHaveBeenCalledTimes'
  • 'toMatch'
  • 'toThrow'
  • 'toThrowError'

Custom Matchers

edit

Sometimes building your own matchers are helpful. A custom matcher can be added in a beforeEach call or within the it call.

describe(“Name of Suite”, function() {
   beforeEach(function () {
	jasmine.addMatchers({
	    toBeCustomMatcher: function(){
		return {
                    compare: function (actual, expected) {
                        return {
                            pass: (actual + someCalculation) === expectedResult
                        };
                    }
                 };
	     }
	});
    });

    it(“what it does”, function() {
       expect(yourJsFunction()).toBeCustomMatcher();
    });
});

Spies

edit

A spy is a way to test if a function has been called and in the way it is supposed to be called

describe(“Name of Spy”, function(){
     it(“calls the [name of] function”, function(){
		spyOn(class, "methodToSpyOn");
		class.aDifferentMethod(input);
		expect(class.methodToSpyOn).toHaveBeenCalledWith(input);
     });
});


Example

edit

Hello World!

edit
  • JavaScript file that needs to be tested Hello.js (Place it in /src directory)
function helloWorld() {
  return "Hello world!";
}
  • JavaScript file with the test case HelloSpec.js (Place it in /spec directory)
describe("Hello world", function() {
  it("says hello", function() {
    expect(helloWorld()).toEqual("Hello world!");
  });
});
  • SpecRunner.html
<!-- include source files here... -->
<script src="src/Hello.js"></script>
<!-- include spec files here... -->
<script src="spec/HelloSpec.js"></script>
  • Run SpecRunner.html in browser
 
SpecRunner.html Results







Shapes

edit
  • JavaScript file that needs to be tested Shapes.js (Place it in /src directory)
function rectangleArea(width, height){
	return width * height;
}

var Shape = function(){};

Shape.prototype.circleCircumference = function(radius){
	this.checkInvalidNumber(radius);
	return 2  * radius * 3.14;
}

Shape.prototype.checkInvalidNumber = function(num){
	if(num <= 0){
		throw new Error("Invalid Number");
	}
}
  • JavaScript file with the test case ShapeSpec.js (Place it in /spec directory)
describe ("Rectangle Area", function(){
	beforeEach(function () {
		jasmine.addMatchers({
			toBeDividedByThree: function(){
				return {
                    compare: function (actual, expected) {
                        return {
                            pass: (actual/3) === 4
                        };
                    }
                };
			}
		});
	});
	
	it('check rectangle area', function(){
		expect(rectangleArea(2, 4)).toBe(8);
		expect(rectangleArea(2,3)).toBeLessThan(8);
		expect(rectangleArea(3,'a')).toBeNaN();
		expect(rectangleArea(3, 4)).toBeDividedByThree();
	});
});

describe("Circle Circumference", function(){
	it( 'check circle circumference has valid number', function () {
		var newShape = new Shape();
		spyOn(newShape, "checkInvalidNumber");
		newShape.circleCircumference(3);
		expect(newShape.checkInvalidNumber).toHaveBeenCalledWith(3);
	});
	
	it( 'check circle circumference', function () {
		var newShape = new Shape();
		expect(newShape.circleCircumference(3)).toBeCloseTo(19, 0);
		expect(newShape.circleCircumference(3)).not.toBeCloseTo(18.8, 1);
		expect(newShape.checkInvalidNumber.bind(null, -3)).toThrow();
		expect(newShape.checkInvalidNumber.bind(null, 7)).not.toThrow();
	});
});
  • SpecRunner.html
<!-- include source files here... -->
<script src="src/Shapes.js"></script>
<!-- include spec files here... -->
<script src="spec/ShapeSpec.js"></script>

In this example there are 2 suites. The first suite is called “Rectangle Area”. It contains 1 specs: “check rectangle area”. Within this spec is 4 matchers. The beforeEach call at the top of the method is used to create the matcher "toBeDividedByThree". The first matcher is “toBe” which checks if the value returned from the method within expect is equal to the argument given to "toBe". The second matcher is “toBeLessThan” which checks if the returned value is less than the argument given to "toBeLessThan". The third matcher, "toBeNaN", checks if the value returned is 'NaN'. The fourth matcher is "toBeDividedByThree" uses the matcher created at the top of the suite. The second suite, "Circle Circumference", has two specs. The first spec uses a spy to see if we indirectly call checkInvalidNumber with a 3 using the matcher “toHaveBeenCalledWith”. The second spec uses the “toBeCloseTo” matcher. This first matcher is used to check if circleCircumference(3) is close to 19 without the decimal place. circleCircumference(3) is 18.84 so 19 is close to 18.84 without the decimal. The second matcher is used to check if circleCircumference(3) is close to 18.8 checking within one decimal place. The third matcher tests the toThrow matcher. Because -3 throws an error within the checkInvalidNumber method this test will return true. The second matcher within this suite checks to see if 7 does not throw an error within the checkInvalidNumber method. The .not operator can be used on all matchers.

See also

edit

References

edit
  1. ^ Davis W. Frank. "Jasmine 1.0 Released". Pivotal Labs. Retrieved 11 February 2014.
  2. ^ https://github.com/jasmine/jasmine/wiki
  3. ^ Github JsUnit Project Page
  4. ^ https://github.com/jasmine/jasmine/releases
  5. ^ http://code.tutsplus.com/tutorials/testing-your-javascript-with-jasmine--net-21229
  6. ^ http://www.htmlgoodies.com/beyond/javascript/testing-javascript-using-the-jasmine-framework.html
edit

Category:JavaScript programming tools Category:Unit testing frameworks