[CakePHP] Unit Testing JavaScript using QUnit and JScoverage
How to run Unit Tests on JavaScript code in CakePHP?
Introduction
As developers, we’re taught the importance of testing right from the beginning. Testing helps us write better code in less time and makes us feel more comfortable with the eventual outcome.
As you know, Pyxis’s system had a lot of JavaScript code which has started building more complex and object-driven and it needs to be covered by proper unit tests. The question is how. I started to try QUnit and JSCoverage to make it easy to run Unit Tests on Pyxis’s JavaScript code which was developed by CakePHP framework.
Installation
I found the JsTests plugin for CakePHP using QUnit and JSCoverage which was written by Dr. Hannibal Lecter.
Step by step to use this plugin for Pyxis:
- Firstly, you should follow the guide how to install of this plugin (link).
- After that, download the latest version of QUnit and replace the old version in your local folder:
path/to/webroot/js/qunit
- Finally, you should be now ready to open the tests in your browser:
[your app root]/js_tests/js_test_runner/run
- When running correctly, the above test runner looks as follows:
QUnit Functions
QUnit doesn’t have a lot of methods and assertions, but that not to say that isn’t fully capable. This is a list of the key tests available:
ok | Assert that a statement is “truthly” |
equal | Assert that two values are equivalent to each other using non-strict comparison. i.e., == |
strictEqual | Make a strict assertion that two values are equivalent to each other. i.e, === |
test | Add a test to the list of tests to run |
asyncTest | Add a test for an asynchronous section of code |
throws | A test to run in the event of an exception being thrown |
Example for assertions method:
test('assertions', function() { // QUnit.ok() QUnit.ok( 1 == 1, 'one equals one, that is truth'); QUnit.ok( false, 'This test will fail'); // QUnit.equal() QUnit.equal( 1, 1, 'one equals one'); QUnit.equal( {}, {}, 'fails, these are different objects'); // QUnit.strictEqual() QUnit.strictEqual("1", 1, 'This test will fail'); })
Structure Your Assertions:
Putting all assertions into a single test case is a really bad idea, because it’s very hard to maintain, and doesn’t return a clean result.
Let’s put them into different test cases, each aiming for a single functionality.
/* Beginning module test 1 */ module("Module 1", { setup: function() { console.log("Just some setup stuff") }, teardown: function() { console.log("Just some teardown stuff") } }); // Function test test('function test module 1', function() { QUnit.ok(doSomething(3, 2) == 5, 'sample test 1'); QUnit.ok(doSomething(8, 2) == 10, 'sample test 2'); }); /* Beginning module test 2 */ module("Module 2"); test('assertions', function() { // QUnit.ok() QUnit.ok( 1 == 1, 'one equals one, that is truth'); });
There’s also great support for test suites with the standard setup() and teardown() type functions you’re used to.
Fixtures:
In QUnit you have a div with the id “qunit_fixture”. You can put markup here and manipulate it in your tests and QUnit will reset it after wards.
It trutly the way to TDD on JavaScript.
module("some dom tests", function() { // Add element to dom $("#qunit_fixture").append("
"); }); test("do some dom stuff",function() { // retrieve equal(1,$("#thing").length); });
Code Coverage
JSCoverage is a tool that measures code coverage for JavaScript programs.
Code coverage statistics show which lines of a program have been executed (and which have been missed).
As result belows, I wrote unit tests code for a file which named Silly.js and this is a summary:
Test code
module('Sample module'); test('Some kind of sample test', function() { QUnit.ok(doSomething(3, 2) == 5, 'sample test 1'); QUnit.ok(doSomething(8, 2) == 10, 'sample test 2'); }); test('Other kind of sample test', function() { QUnit.ok(doSomethingElse(3, 2) == 8, 'sample test 3'); QUnit.ok(doSomethingElse(8, 2) == 18, 'sample test 4'); }); test('A failing test', function() { QUnit.ok(doSomethingElse(3, 2) == 81, 'sample test 5'); QUnit.ok(doSomethingElse(8, 2) == 8, 'sample test 6'); QUnit.ok(doSomething(5, 2) == 7, 'sample test 7'); }); module("Show and Hide Module"); test("should show the element when show is called", function(){ $("#testDiv").hide(); makeItShow(2); // actual, expected QUnit.equal($("#testDiv").is(":visible"), true, "The element should be hidden"); });
The result:
Conclusion
This was a rapid introduction to QUnit, one of the simplest and most effective unit testing libraries for JavaScript. Unit testing is a great method to test your code before publishing it.
If you haven’t written any unit tests JavaScript before, it’s time to get started!
Thanks for reading!