User:Divyajain2405/jasmine

Jasmine is an open source development framework for testing JavaScript. 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. The developers at Pivotal Labs developed a similar unit testing framework called JsUnit before the active development of Jasmine. , and the first version was released on September 14th 2010.Jasmine is suitable for any project that has JavaScript running.

Installation
The latest standalone version is available to download, at https://github.com/jasmine/jasmine The resulting directory has the following structure:



Folders and their meanings

 * 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

Key terms

 * Suite: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”); }); });

File Setup & Running the test

 * 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
In some situations a programmer may need a few lines of code to be performed for every test. Jasmine provides  &  functions which allow Jasmine to run the code before and after each test, respectively. These functions eliminate writing redundant code for every  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.

Predefined Matchers (v.2.3.4)

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

Custom Matchers
Sometimes building your own matchers are helpful. A custom matcher can be added in a  call or within the   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
A spy is a way to test if a function has been called and in the way it is supposed to be called Spies are useful to determine statistics like how many times the function was called, with what parameters and what value was returned to the caller. describe(“Name of Spy”, function{    it(“calls the [name of] function”, function{ spyOn(class, "methodToSpyOn"); class.aDifferentMethod(input); expect(class.methodToSpyOn).toHaveBeenCalledWith(input); }); });

Hello World!
function helloWorld { return "Hello world!"; } describe("Hello world", function { it("says hello", function { expect(helloWorld).toEqual("Hello world!"); }); });
 * JavaScript file that needs to be tested Hello.js (Place it in /src directory)
 * JavaScript file with the test case HelloSpec.js (Place it in /spec directory)
 * SpecRunner.html




 * Run SpecRunner.html in browser



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

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"); } } 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; }); });
 * JavaScript file with the test case ShapeSpec.js (Place it in /spec directory)

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





In this example there are 2 suites. The first suite is called “Rectangle Area”. It contains 1 spec: “check rectangle area”. Within this spec are 4 matchers. The  called 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", which 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. The first “toBeCloseTo” 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 “toBeCloseTo” 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 fourth matcher within this suite checks to see if 7 does or does not throw an error within the checkInvalidNumber method. The .not operator can be used on all matchers.

Comparison of Jasmine with other frameworks

 * Testing frameworks like qUnit and YUI are specific to a particular JS Library but Jasmine provides test classes not tied to any specific framework.
 * Jasmine doesn't rely on browser unlike some other JavaScript testing frameworks.