Automated Unit Tests using QUnit JS in an Oracle JET project
Update July 2019 — I would no longer recommend using QUnit for testing JET applications. Jasmine or Jest are both better alternatives. You can find out more information about how to setup and use Jasmine within an Oracle JET application in Chapter 13 of Practical Oracle JET.
Why is unit testing always a sore subject? It shouldn't be, but it takes a multitude of things to come together to ensure a team of developers write good automated unit tests for their work. One of these is deciding on a unit test framework to use (it’s a bit of a maze out there), and making it really easy for developers to write their tests.
The last thing you want to worry about when you are facing tight deadlines is having to learn a new testing framework, on top of the pile of other tasks you likely have on your backlog. Hopefully, the next few minutes will give you a head start in getting a skeleton unit test framework working in your project, ready for those important automated tests to be written.
This article demonstrates QUnit within an Oracle JET project, QUnit is the chosen framework as there is plenty of support, and it is one of the reccomended frameworks to use for JET.
The examples below were written in Oracle JET 4.1
Create your folder structure
First of all, create a folder in your /src/ folder named ‘tests’. In order for the watch task to monitor for changes on your tests (supported in JET v4+), you must have all your unit tests within the /tests/ directory.
You will also want to create src/tests/modules and src/tests/data folders too, this will hold all your modulated QUnit test files and mock JSON payloads.
Note: It is possible to change the directory name for your tests (as it is for all your src folder paths) - in oraclejetconfig.json.
You will notice that if you now do an ojet build, JET acknowledges that you now have unit tests in your app, and will automatically start bringing the QUnit library over into your web/libs folder — sweet!
Import mockjax
jquery-mockjax is a really useful plugin that provides a handle onto AJAX responses, so that you can manipulate the response and return mock data to your tests.
To install mockjax run the following:
npm install jquery-mockjax --save
Once this has completed, you need to copy the library files over to your application’s staging directory. Make the following change to your /scripts/oraclejet-build.js file:
copyCustomLibsToStaging: {
fileList: [
{
cwd:'node_modules/jquery-mockjax/dist',
src: ['jquery.mockjax.js'],
dest: 'web/js/libs/jquery-mockjax'
}
]
},
Setup your entry point
You must create two files for your entry point for your tests. One is your index.html, where you will initiate your tests, and see the results. The second is your main.js file.
Create a new main.js file in your src/tests/ directory, this will be the entry point for your unit tests to run, and will load all the require.js dependencies and test modules.
The main.js will be similar to the one that you use for your JET application, with a couple of changes. So as a starting point you can copy over the contents from src/js/main.js, and make the following changes:
- Your baseUrl value will be slightly different. You’ll have to change this to move up one directory, so it would be ../js instead of just js.
- Ensure you have added mockjax and your viewModel dependancies
- The require block will be different, as it is used to load all your test modules and also initiate QUnit. You may want to add extra functionality into this block at a later stage.
require path config
requirejs.config(
{
baseUrl: '../js',
// Path mappings for the logical module namespaths:
{
'knockout': 'libs/knockout/knockout-3.4.0.debug',
'jquery': 'libs/jquery/jquery-3.1.1',
'jqueryui-amd': 'libs/jquery/jqueryui-amd-1.12.0',
'promise': 'libs/es6-promise/es6-promise',
'hammerjs': 'libs/hammer/hammer-2.0.8',
'ojdnd': 'libs/dnd-polyfill/dnd-polyfill-1.0.0',
'ojs': 'libs/oj/v4.0.0/debug',
'ojL10n': 'libs/oj/v4.0.0/ojL10n',
'ojtranslations': 'libs/oj/v4.0.0/resources',
'text': 'libs/require/text',
'signals': 'libs/js-signals/signals',
'customElements': 'libs/webcomponents/custom-elements.min',
'proj4': 'libs/proj4js/dist/proj4-src',
'css': 'libs/require-css/css',
'mockjax': 'libs/jquery-mockjax', // View Models
'dashboardViewModel': 'viewModels/dashboard.js' }, shim:
{
'jquery':
{
exports: ['jQuery', '$']
}
}});
require block
var testModules = [ // General Imports 'jquery',
'knockout',
'appController',
'mockjax', // Test Suites - add all your test modules here
'modules/dashboardTests.js'
];require(testModules, function ($, ko, app) {
ko.applyBindings(app, document.getElementById('globalBody'));
QUnit.start();
});
Your index file will look like this, and will be stored within src/tests/index.html
<!DOCTYPE html> <html> <head> <title>My first Oracle JET QUnit Tests</title>
<link rel="stylesheet" href="../js/libs/qunit/qunit.css"> </head> <body> <div id="qunit"></div>
<div id="qunit-fixture"></div>
<script src="../js/libs/qunit/qunit.js"></script>
<script data-main="main" src="../js/libs/require/require.js">
</script> <div id="globalBody"></div>
<script type="text/javascript" charset="utf-8">
QUnit.config.autostart = false;
</script> </body>
</html>
Create your dashboardTests.js file
Now that you have your framework in place, you can start writing your tests! I wont go into detail on how QUnit tests work, as this is all documented quite extensively online, and on the QUnit website.
I will show a quick example of how to run a QUnit test in an Oracle JET application.
Example of dashboard viewModel
Imagine I have an external service that returns a date. I then do a check on this date to see if matches with todays date. The result is stored within an observable.
self.dateBoolean = ko.observable();self.runService = function() { // AJAX call and date check logic self.dateBoolean(result);};
Example dashboardTests.js
Now I want to write a test, to ensure my date logic is correct. We can use mockjax to modify the response payload, so I have full control over what date the service call returns.
My mock response will be stored in data/dashboard.json, and assigned to the mockjax proxy attribute.
require(['dashboardViewModel'], function (viewModel) { QUnit.module("Dashboard tests", {}); var vm = new viewModel(); function init(){
$.mockjax({
url: 'http://myservicelocation',
type: 'GET',
responseTime: 0,
contentType: 'text/json',
proxy: 'data/dashboard.json'
});
} QUnit.test("Sample test", function (assert){
init();
vm.runService();
var done = assert.async(); setTimeout(function () {
assert.equal(vm.dateBoolean(), true, "Dates matched");
done();
}, 100);
});
});
For more information on how to use QUnit, please visit the website, which contains a lot of useful examples:
— DC
[1] Image Credit — http://toolsqa.com/software-testing/software-testing-tutorial/