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 user actions (Medium)


In this recipe, we will write a simple calculator widget. By testing, we will simulate end-user actions and assert the intended application behavior.

Getting ready

Before jumping on the test, we definitely need an application expecting user actions. Let it be a simple calculator that cannot do complex operations but will sum up two of the supplied numbers, as seen in the following screenshot:

To make it work, we subscribe a handler to the click event on the Calculate button. The handler takes the values of the first and second fields, sums them up, and puts the result in the third field. The implementation of the code is as follows:

"strict mode";

this.utils = {
    /**
     * Fire a suplied event on a given element
     * @param {object} el instance of HTMLElement
     * @param {string} eventName
     */
    trigger: function( el, eventName ) {
        var e = document.createEvent("Event");
        e.initEvent( eventName, true, true );
        el.dispatchEvent( e );
    },
    /**
     * Subscribe handler for event on a supplied element
     * @param {object} el instance of HTMLElement
     * @param {string} eventName
     * @param {function} handlerCb
     */
    subscribe: function( el, eventName, handlerCb ) {
        el.addEventListener( eventName, function( e ) {
            handlerCb( e ); 
        }, false );
    }
};

(function( global ){
  var document = global.document,
      utils = global.utils;

  utils.subscribe( global, "load", function() {
    utils.subscribe( document.getElementById("calc"), "click", function( e ) {
      var num1 = document.getElementById("num1"),
          num2 = document.getElementById("num2"),
          sum = document.getElementById("sum");

      e.preventDefault();
      sum.value = parseInt(num1.value, 10) +
        parseInt(num2.value, 10);
    });  
  });
}( this )); 

Let's save the source code into the calc.js file and load it from the HTML layout:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <title>Calc</title>
        <link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-combined.min.css" rel="stylesheet">
        <style>
          .container {
            margin: 32px;
          }
        </style>
    </head>
    <body>
    <div class="container">
      <form class="form-inline">
        <input id="num1" type="text" class="input-small" placeholder="Summand">
        <span>+</span>
        <input id="num2" type="text" class="input-small" placeholder="Summand">
        <span>=</span>
        <input id="sum" type="text" class="input-small" placeholder="Sum">
        <button  id="calc" type="button" class="btn btn-primary">Calculate</button>
        <button type="reset" class="btn btn-danger">Reset</button>
      </form>
    </div>
    <script src="./js/calc.js"></script>
    </body>
</html>

Now, we run this HTML in a browser and test it manually. With numbers typed in, the button clicked, and the result received, we are now ready to write an automated test for the actions we just performed.

How to do it

  1. Subscribe a handler to the DOM-ready event and get references on the involved elements. To mimic a user typing numbers and clicking the button, we need to refer to the inputs and the button. However, elements will be available only when the DOM tree is built. So, we obtain references on the elements in the handler, which is called on the DOM-ready event. For that, we use the helper introduced in the sample application as follows:

    utils.subscribe( global, "load", function() {
                 var calc =  document.getElementById("calc"),
                     num1 = document.getElementById("num1"),
                     num2 = document.getElementById("num2"),
                     sum = document.getElementById("sum");
    });
  2. Define a test scope and simulate the user behavior. Within the scope, we assign test values to inputs and trigger the click event. Since the application responds to the click event immediately, we can synchronously assert that the value in the result field equals the sum of numbers we supplied.

    utils.subscribe( global, "load", function() {
                 var calc =  document.getElementById("calc"),
                     num1 = document.getElementById("num1"),
                     num2 = document.getElementById("num2"),
                     sum = document.getElementById("sum");
                    
                QUnit.test( "Test that calc sums up typed in numbers by click", function( assert ){
                    num1.value = "5";
                    num2.value = "7";
                    utils.trigger( calc, "click" );
                    assert.strictEqual( sum.value, "12" );
                });
      });
  3. Load the test runner in a browser and examine the results shown in the following screenshot: