Performance Zone is brought to you in partnership with:

I am a web developer at Crytek GmbH. As for my open source contributions, some were pretty popular once Sapid CMS, AOP library for PHP, few plugins for jQuery. Numerous of my works were published in specialized medias, I have been a speaker at developer conferences (e.g. PHP Conf), and published articles in magazines such as PHP Architect and PHP Magazine International Dmitry is a DZone MVB and is not an employee of DZone and has posted 9 posts at DZone. You can read more from them at their website. View Full User Profile

Performing Functional Testing with qUnit

10.28.2012
| 4630 views |
  • submit to reddit

Automated testing is an essential part of application life-cycle (see Continuous Integration). In web-development we usually test: Back-end (*Unit-tests), Front-end (HTML/CSS validators, JSLint/JSHint, CSSLint, YSlow etc) and UI (functional testing). Unit-testing (Back-end, Front-end) is about checking if all the application components adhere the technical design requirements. Every unit-test simulates the application environment on which runs. Functional tests are to determine if the application as a whole ecosystem has no flaws. They run on a copy of real application environment and show if everything is ok from user prospective. You can see it as an automation of QA-engineer routine where it is possible. For functional testing widely used such frameworks as Selenium, Windmill, Twill, BusterJS. Though, if you use qUnit for front-end unit-testing, you may love the idea to use the same tool on functional testing. jQuery provides an incredible API for DOM manipulation. It can be amazing tool to simulate user behaviors and check DOM reaction.

Thanks to Michel Gotta's post I came up with a solution.

Configuration

You just feed UiTester with the list of UIs that you want to test in the qUnit report generator file:

<div id="playground"></div>
        <h1 id="qunit-header">QUnit example</h1>
        <h2 id="qunit-banner"></h2>
        <div id="qunit-testrunner-toolbar"></div>
        <h2 id="qunit-userAgent"></h2>
        <ol id="qunit-tests"></ol>
        <div id="qunit-fixture">test markup, will be hidden</div>

<script type="text/javascript">
(function( $, window, undefined) {

   $(window.document).ready(function(){
        UiTester.init( $, {
            testsuites : [
                {suit : "example1", url: "ui-form-example.html"},
                {suit : "example2", url: "ui-widget-example.html"}
            ],
            wwwRoot : "./../"
        });
    });

}( jQuery, window ));
</script>

By this we assume that we have 2 pages (here just 2 HTML files) related to the test-suits examples1 and example2 respectively. That can be any URLs of the same domain with testing tool. So UiTester will iterate through testsuites array, loading defined url in the iframe and running the test suit corresponding the suit value.

Tests

Now let's see what the tests look like:

var TestSuit =  function( $, proceed) {
    return {
         example1: function() {
               // qUnit tests
               proceed();
         },
         example2: function() {
               // qUnit tests
               proceed();
         }
   }
}

The tests placed in the scope of a function which introduces actual jQuery instance (every UI has own) and proceed function which points out where all the tests of the suit are complete. In this this particular example the tests are assumed to be synchronous and proceed always goes at the end of the suit. However, it wouldn't work with the asynchronous tests. The end of the function will be reached before tests really performed. So, you have to call proceed() within the last asynchronous test callback next to start().

var TestSuit =  function( $, proceed) {
    return {
         example: function() {
               // qUnit tests
               asyncTest( "The last async test", 1, function() {
                    window.setTimeout(function() {
                        ok( true, "All is fine" );
                        start();
                        proceed();
                    }, 500);
                });
         }
   }
}

Assertion helpers

Writing tests for DOM I found that I needed a helper to make the assertion flow more readable:

test( "Test DOM", function() {
        testNodes([
            {node: "selector",
                assert: "exists",
                msg: "Selector found"
            },
            {node: "selector",
                assert: "visible",
                msg: "Selector visible"
            },
            {node: "selector",
                assert: "checked",
                msg: "Selector checked"
            }
        ]);
    });

 

So, ui-tester.js contains extendQUnit with a set of available assertion helpers extending qUnit standard set. Currently the only helper in there is testNodes, but you can easily extend it anytime.

Now we can run report generator (/tests-js/index.html) and examine how the test pass.


In Command Line

Fancy to run the tests on the console? That can be done with e.g. phantomjs:

phantomjs run-qunit.js http://project.my/tests-js/index.html

'waitFor()' finished in 1300ms.
Tests completed in 1167 milliseconds.
25 tests of 25 passed, 0 failed.

Just don't forget to change Default Max Timeout value in run-qunit.js.

 

Published at DZone with permission of Dmitry Sheiko, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)