I'm using QUnit in conjunction with require.js for unit-testing a backbone.js application. All of the tests are asynchronous, using the asyncTest
method.
I'm using setup
and teardown
to build and remove a fixture for each test. My problem is that although asyncTest
seems to be blocking, setup()
gets called for each test before they start, pretty much all setup()
calls run at the same time. This solution doesn't seem to fix my problem. Below I have an example of how I set up the module and here's a link to a test repository that illustrates the problem
My question is: Am I doing something wrong or is this QUnit's normal behaviour?
module('Module', {
setup: function(){
console.log('setup');
},
teardown: function(){
console.log('teardown');
}
})
asyncTest('Test 1', function() {
setTimeout(function(){
equal(2, 2, 'The return should be 2.');
start();
}, 400);
});
asyncTest('Test 2', function() {
setTimeout(function(){
equal(1, 1, 'The return should be 1.');
start();
}, 400);
});
I'm using QUnit in conjunction with require.js for unit-testing a backbone.js application. All of the tests are asynchronous, using the asyncTest
method.
I'm using setup
and teardown
to build and remove a fixture for each test. My problem is that although asyncTest
seems to be blocking, setup()
gets called for each test before they start, pretty much all setup()
calls run at the same time. This solution doesn't seem to fix my problem. Below I have an example of how I set up the module and here's a link to a test repository that illustrates the problem
My question is: Am I doing something wrong or is this QUnit's normal behaviour?
module('Module', {
setup: function(){
console.log('setup');
},
teardown: function(){
console.log('teardown');
}
})
asyncTest('Test 1', function() {
setTimeout(function(){
equal(2, 2, 'The return should be 2.');
start();
}, 400);
});
asyncTest('Test 2', function() {
setTimeout(function(){
equal(1, 1, 'The return should be 1.');
start();
}, 400);
});
Share
Improve this question
edited May 23, 2017 at 12:05
CommunityBot
11 silver badge
asked Jun 12, 2013 at 12:26
Julian Krispel-SamselJulian Krispel-Samsel
7,7444 gold badges35 silver badges41 bronze badges
7
- You should take a look at Sinon. It's worth spending some time learning it, really helps with async testing. – gustavohenke Commented Jun 12, 2013 at 13:20
- @gustavohenke which part of sinon are you referring to? I had a look at it but only for it's mocking, stubbing, spying stuff. – Julian Krispel-Samsel Commented Jun 12, 2013 at 13:24
- when you need to deal with timing, fake timers are handy :) – gustavohenke Commented Jun 12, 2013 at 13:27
- Ah right. For brevity, I'm using setTimeout as a replacement for my AJAX callbacks really. So replacing setTimeout isn't the right solution I'm afraid. Considering that, have you got another idea? – Julian Krispel-Samsel Commented Jun 12, 2013 at 13:32
- Sinon can also fake the XMLHttpRequest or even a full server with routes and custom headers/status codes. You'll never more need to trust your server for testing AJAX :) – gustavohenke Commented Jun 12, 2013 at 13:42
2 Answers
Reset to default 6QUnit expects a rather specific page load behaviour. Loading it via requirejs might look like it works, but actually doesn't. The remendation is to load QUnit via a regular script tag. Loading the tests itself via requirejs is fine, as long as you set QUnit.config.autostart = false
, as you do.
Blogpost including the solution Jörn Zaefferer specifies above - http://www.jonnyreeves.co.uk/2012/qunit-and-requirejs/
here's what I implemented-
Problem I was having:
I included qunit via require. This seemed to work fine for all synchronous tests. I was defining a variable in my qunit module's setup and back to null on teardown. When I included an asyncTest, it seemed to not be reset properly by the teardown and was thus breaking all the tests that ran after that one that expected a fresh variable.
Key points
- Include qunit via its own script tag
- set autostart to false
- start again after all test modules are required
It's probably not the most elegant, but I also didn't run across any end to end examples, and I just burned a couple hours finding this answer (since I first thought that I was setting my asyncTest up incorrectly).
<link rel="stylesheet" href="qunit-1.12.0.css">
<script type="text/javascript" src="qunit-1.12.0.js"></script>
<script>
QUnit.config.autostart = false
require(['App'],
function(){
//Modules that have been loaded in by require.js
var loadedModules = [];
//Locations of test modules to load
var moduleLocations = [
'tests/test1',
'tests/test2',
'tests/test3'
];
//If all modules have been loaded, run them
function runTests(){
if (loadedModules.length == moduleLocations.length){
QUnit.start();
_.each(loadedModules,function(test){
test();
});
}
}
_.each(moduleLocations,function(string){
require([string],
function(a){
loadedModules.push(a);
runTests();
});
});
});
</script>
Separate Test Module Files:
define(['array','of','test','requirements'], function() {
return function(){
var options = null;
module('Autoplete',{
setup: function() {
// prepare something for all following tests
options = new whatever();
},
teardown: function() {
// clean up after each test
options = null;
}
});
test( "normal tests", function() {
ok(true,"normal assertions");
});
}
});