First look to javascript unit test framework – ExpectJs

Today I going to write about javascript unit test frameworks, to be more specific, about Expectjs.
Sometimes web developers ignores the action of testing their code, automated, just because it works in
some random manual attempts. Just a reduced number of developers really like the activity of write unit test because of the security and the mind peace it brings to any development process.
This time let’s take a look at ExpectJS, a minimalistic BDD assertion toolkit based on should.js that
provides very useful features to developers in order to test their codes through unit test. But how it
works exactly? In this post I’d like to expose the main features and APIs of this amassing library.
 
javascript unit test framework

Two definitions before go to the main topic: Assertions + Unit Testing with ExpectJs

Basically an assertion is a statement where a Boolean-valued function is expected to be true at that
point in the code. If the assertion evaluates to false in some point of the execution, it will throw an
assertion exception. For example:

 
function assert(condition, message) {
    if (!condition) {
        throw message || "Assertion failed";
    }
}
 

In the other hand, a unit test checks blocks of code to ensure that they all run as expected. Simple JavaScript unit test will take a function, monitor output and return its behavior, and assertions are used in the process. Sometimes this task is not so easy with vanilla JavaScript.

Other javascript unit test frameworks

There are other options. Out there are plenty of javascript unit test frameworks like QUnit, Sinon, Mocha or Jasmin, all of them are able to integrate assertions libraries like ExpectJS.

Let’s get starting with ExpectJS

How to install it.
 
Node
Install it with NPM or add it to your package.json:
$npm install expect.js
Then you can use the following code:

var expect = require('expect.js');

Browser

<!-- download the file to your local -->
<script src="expect.js"></script>

<!-- from a CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/expect.js/0.2.0/expect.js">
</script>

 

Main features

– Cross-browser: works on IE6+, Firefox, Safari, Chrome, Opera.
– Compatible with all test frameworks.
– Node.JS ready (require(‘expect.js’)).
– Standalone. Single global with no prototype extensions or shims.

Our first test

Let’s say we want to test the following add function:

function add(a, b) {
return a – b; 
};

expect(add).to.be.a('function');  // this assertion passes
expect(add(1, 3)).to.equal(4);  // this assertion fail
expect(add(5, 2)).to.be.lessThan(8); // this assertion passes

Now, notice that if we execute this code, and we check the console of the browser you’ll see an error for the assertion that failed (the second one).

 
Try it yourself

The previous approache is not too intuitive, so lets wrap it up with a framework that offers a more visual result, lets use MochaJs:

Comparing with other assertion test frameworks

Differences with should.js
– No need for static shouldjs methods like should.strictEqual(). For example, expect(obj).to.be(undefined) works well. More intuitive now!
– Some API simplifications/changes.
– API changes related to browser compatibility.

Let’s see how intuitive the ExpectJS API’s can be.

Example 1: a/an: asserts typeof with support for array type and instanceof (used with mocha testing framework)

describe("Example 1", function() {

 var n;
 var cars;

it("number check", function() {
    n = 'good';
    expect(n).to.be.a('number');
  });


  it("array and object check", function() {
    cars =['Mercedes', 'Toyota', '4x4'];
  
   expect(cars).to.be.an('array'); // it works
   expect(cars).to.be.an('object'); // it Works too since it supports typeof
  });
});

Example 2: match: asserts String regular expression match. We can use useful regular expressions like this:

describe("Regular expressions check", function() {
 var version;
it("version check", function() {
    n = '4.8.2';
    expect(version).to.match(/[0-8]+\.[0-8]+\.[0-8]+/);
  });
});

Try it yourself

Other resources the API provides:

ok: asserts that the value is truthy or not.

expect(1).to.be.ok();

eql: asserts loose equality that works with objects.

expect({ a: 'b' }).to.eql({ a: 'b' });

contain: asserts indexOf for an array or string.

expect([1, 2]).to.contain(1);

length: asserts array .length.

expect([]).to.have.length(0);

empty: asserts that an array is empty or not.

expect([]).to.be.empty();

property: asserts presence of an own property (and value optionally).

expect(window).to.have.property('expect')

key/keys: asserts the presence of a key. Supports the only modifier.

expect({ a: 'b' }).to.have.key('a');

throw/throwException/throwError: asserts that the Function throws or not when called.

expect(fn).to.throw(); // synonym of throwException.

withArgs: creates anonymous function to call fn with arguments.

expect(fn).withArgs(invalid, arg).to.throwException();

within: asserts a number within a range.

expect(1).to.be.within(0, 100);

greaterThan/above: asserts.

expect(3).to.be.above(0);

lessThan/below: asserts.

expect(0).to.be.below(3);

fail: explicitly forces failure. (This is very helpful sometimes).

expect().fail()

How to use it with spies.

A way to verify the function behavior in unit test is through the use of spies. A spy allows you to monitor a function exposing options to track invocation counts, arguments and return values. The main principle here is that it replaces a particular function where you want to control its behavior in a test, and record how that function is used during the execution of that test (similar to how actors are replaced with stunt doubles for dangerous action scenes in Hollywood movies).

Let’s see how it works: (Other examples can be found here)

spyOn(foo, 'bar');  // Here the spyOn method takes an object and a method to be spied upon.
foo.bar(1);         // Call the function
 
expect(foo.bar).toHaveBeenCalled(); // Run assertions with ExpectJS.
expect(foo.bar).toHaveBeenCalledWith(1);

Final considerations.

ExpectJS is a very useful assertion library and combined with other javascript unit test frameworks can be very visual and can save a lot of time while provide security to your code. Other libraries similar are Chai, should.js, and better-assert. One of the advantages is that it is Standalone and can be integrated with any javascript unit test frameworks.

References:

https://github.com/Automattic/expect.js/blob/master/README.md
https://abdulapopoola.com/2016/04/11/how-function-spies-work-in-javascript/
https://designmodo.com/test-javascript-unit/

Leave a Reply

Your email address will not be published. Required fields are marked *