Book Image

Instant Testing with QUnit

By : Dmitry Sheiko
Book Image

Instant Testing with QUnit

By: Dmitry Sheiko

Overview of this book

<p>Automated testing is a significant part of agile development. QUnit is widely used in the jQuery Project for testing jQuery, jQuery UI, and jQuery Mobile; it can also be used to test any generic JavaScript code. As for JavaScript testing in particular, QUnit is a good choice for a framework as users can grasp the basics in a short span of time. The framework is a leading tool for unit and acceptance testing and can be used in conjunction with a wide range of third-party software. Instant Testing with QUnit covers all the essentials of QUnit and explains how you can use the framework in combination with other tools to improve your development process.</p><p>"Instant Testing with QUnit" is a hands-on guide that will help you achieve beneficial automated testing with QUnit and its plugins. This book also shows you how to engage QUnit for automated cross-browser testing and utilize it in conjunction with development automation and Continuous Integration tools.</p><p></p><p>"Instant Testing with QUnit" provides a comprehensive look into QUnit essentials and shows how you can benefit from the framework in conjunction with other tools. You will start by considering QUnit fundamentals before learning how QUnit can be used for functional testing and cross-browser automated testing with the Bunyip tool. You will also walk through a tutorial on popular QUnit plugins and then write one of your own. By the end of Instant Testing with QUnit, you will have learned how to run QUnit in the command line and how to set up the Jenkins CI server and make it perform QUnit tests.</p>
Table of Contents (7 chapters)

Testing exceptions (Medium)


In this recipe, we will learn how to handle the function's exceptional behavior, how to define custom exceptions, and how to test exceptions are really thrown for invalid input and these are exceptions of the intended types.

Getting ready

We've learnt already how to test whether or not a function performs the intended business logic. But what about its exceptional behavior? Let's say we supply invalid input parameters. We expect the function to warn us about them. The best practice would be to check the parameters have been passed onto the function entry point and thrown exceptions if any of the parameters are invalid. We need a way to test this logic as well.

Do you remember the utils.trim function example? We have to modify it now for checking the validity of the input parameters:

var trim = function( str, charlist ) {

  if ( typeof str !== "string" ) {
    throw new this.InvalidTypeException("str argument must be a string");
  }
  if ( charlist && typeof charlist !== "string" ) {
    throw new this.InvalidTypeException("charlist argument must be a string");
  }
  if ( !str.length ) {
    throw new this.InvalidReferenceException("str argument must be empty");
  }

  charlist = charlist || " \t\n\r\0\x0B";
  return str.replace( new RegExp( "^[" + charlist + "]+|[" + charlist + "]+$", "g" ), '' );
}

Well, the function throws exception whenever it detects an invalid input but these are custom exceptions that must be defined. This can be done by declaring new error object constructors that inherit from standard JavaScript errors. Please find the implementation for this in the following example:

"strict mode";
var utils = (function( global ) {
  "use strict";
  return {
    /**
     * Port of PHP trim function 
     * @param {string} str
     * @param {string} charlist
     * @return {string}
     */
    trim: function( str, charlist ) {
    // function body from the example above
   },
    /**
    * @constructor
    */
    InvalidReferenceException: function( message ) {
       this.name = "InvalidReferenceException";
       this.message = message || "InvalidReferenceException thrown";
    },
    /**
    * @constructor
    */
    InvalidTypeException: function( message ) {
       this.name = "InvalidTypeException";
       this.message = message || "InvalidTypeException thrown";
    }
  };
}());

 // Inherit from ReferenceError
utils.InvalidReferenceException.prototype = new ReferenceError();
utils.InvalidReferenceException.prototype.constructor = utils.InvalidReferenceException;
// Inherit from TypeError
utils.InvalidTypeException.prototype = new TypeError();
utils.InvalidTypeException.prototype.constructor = utils.InvalidTypeException;  

How to do it

  1. Define the test scope and the assert expected exception is thrown. In this case, QUnit provides the throws method, which can be described with the following code:

    QUnit.test( "Test title", function( assert ) {
      assert.throws( "callback throwing exception, expected exception", "assertion title" );
    });
  2. Test whether utils.trim validates the input parameters and throws the intended exceptions:

    QUnit.test( "Test utils.trim contract violation", function( assert ){
      assert.throws( function() {
          utils.trim("");
        }, utils.InvalidReferenceException, 
        "str agrument must not be empty" 
      );
      assert.throws( function() {
          utils.trim( 1 );
        }, utils.InvalidTypeException, 
        "str agrument must be a string" 
      );
      assert.throws( function() {
          utils.trim( "string", 1 );
        }, utils.InvalidTypeException, 
        "charlist agrument must be a string" 
      );
    });
  3. Load the test runner in a browser and examine the results shown in the following screenshot: