Testing JavaScript using JASMINE

What is Jasmine?

  • Jasmine is a behavior-driven development (BDD) framework for testing JS code

  • It does not depend on any other JS frameworks

  • It does not require a DOM

  • It has a clean, obvious syntax

describe("A suite", function() {
  it("contains spec with an expectation", function() {
    expect(true).toBe(true);
  });
});

Suites: describe your code

A test suite begins with a call to the global Jasmine function describe with two parameters: a string and a function.

  • The string is a name or title for a test suite – usually what is being tested.
  • The function is a block of code that implements the suite.

Suites: describe your code

// This is a suite
describe("Player", function() {
  var player;
  var song;

  beforeEach(function() {
    player = new Player();
    song = new Song();
  });

  it("should be able to play a Song", function() {
    player.play(song);
    expect(player.currentlyPlayingSong).toEqual(song);
  });

});

Suites: Nesting describe Blocks

Calls to describe can be nested, with specs defined at any level. This allows a suite to be composed as a tree of functions

// This is a suite
describe("Player", function() {
  var player;
  var song;

  beforeEach(function() {
    player = new Player();
    song = new Song();
  });

  it("should be able to play a Song", function() {
    player.play(song);
    expect(player.currentlyPlayingSong).toEqual(song);
  });
  
  // This is a suite inside a suite 
  describe("when song has been paused", function() {
    beforeEach(function() {
      player.play(song);
      player.pause();
    });

    it("should indicate that the song is currently paused", function() {
      expect(player.isPlaying).toBeFalsy();
    });

    it("should be possible to resume", function() {
      player.resume();
      expect(player.isPlaying).toBeTruthy();
      expect(player.currentlyPlayingSong).toEqual(song);
    });
  });

});

Specs

Specs are defined by calling the global Jasmine function it, which, like describe takes a string and a function.

  • The string is the title of the spec and the function is the spec, or test.
    • A spec contains one or more expectations that test the state of the code.
    • A spec with all true expectations is a passing spec.
    • A spec with one or more false expectations is a failing spec.

Specs

describe("Player", function() {
  var player;
  var song;

  beforeEach(function() {
    player = new Player();
    song = new Song();
  });

  // this is a spec
  it("should be able to play a Song", function() {
    player.play(song);
    expect(player.currentlyPlayingSong).toEqual(song);
  });

});

Specs: before and after

describe("Player", function() {
  var player;
  var song;

  beforeEach(function() {
    player = new Player();
    song = new Song();
  });

  it("should be able to play a Song", function() {
    player.play(song);
    expect(player.currentlyPlayingSong).toEqual(song);
  });

  afterEach(function(){
    player = null;
    song = null;
  });

});

beforeEach() -> takes a function that is executed before each spec

afterEach() -> takes a function that is executed after each spec

Expectations & Matchers

Expectation

  • assertion that is either true or false

  • built with the function expect which takes a value, called the actual.

  • it is chained with a Matcher function, which takes the expected value.

Matcher

  • used to evaluate the behavior of your code
  • implements a boolean comparison between the actual value and the expected value.
  • responsible for reporting to Jasmine if the expectation is true or false. Jasmine will then pass or fail the spec

Expectations & Matchers

describe("Player", function() {
  var player;
  var song;

  beforeEach(function() {
    player = new Player();
    song = new Song();
  });

  it("should be able to play a Song", function() {
    player.play(song);
    
    // expectation and matcher
    expect(player.currentlyPlayingSong).toEqual(song);
  });
});

Custom Matcher

describe("Player", function() {
  var player;
  var song;

  beforeEach(function() {
    player = new Player();
    song = new Song();

    jasmine.addMatchers({
        toBePlaying: function () {
          return {
            compare: function (actual, expected) {
              var player = actual;
    
              return {
                pass: player.currentlyPlayingSong === expected && player.isPlaying
              };
            }
          };
        }
      });  
  });

  it("should be able to play a Song", function() {
    player.play(song);
    expect(player.currentlyPlayingSong).toEqual(song);

    //demonstrates use of custom matcher
    expect(player).toBePlaying(song);
  });
});

Spies

Text

deck

By pgamilde

deck

  • 865