On Github katbailey / qunit-talk
Presented by Kat Bailey / @katherinebailey
Big thanks to Jordan Kasper aka @jakerella whose slides on this topic I borrowed heavily from. See http://jordankasper.com/js-testing
Although I focus here on QUnit and Sinon JS, there are other frameworks, e.g. Jasmine and jQuery Mockjax, that provide very similar functionality. The ideas are generally the same across all of these frameworks.
Call Stack (anonymous) app.min.js 3 (anonymous) app.min.js 3 (anonymous) app.min.js 3 (anonymous) app.min.js 3In production we may have minified code, and be unable to see what's really going on. Even if it isn't minified, this can make for much easier diagnosis of a problem.
(and then refactor a little more)
Discuss refactoring in chuncks, abstract one thing at a timeCall Stack jk.handleResults app.min.js 3 successHandler app.min.js 3 jk.doSearch app.min.js 3 submitHandler app.min.js 3 jk.initSearch app.min.js 3 initPage index.html 376
$(document).ready(function() { if (Drupal.settings.hasOwnProperty('personalization')) { var settings = Drupal.settings.personalization; var $option_set = $(settings.selector); $.ajax({ 'url': 'http://www.my-personalization-service.com/get-decision', 'data': {'options': settings.options}, 'success': function(response) { var choice = response.data.choice; // [Various edge case logic...] var json = $('script[type="text/template"]', $option_set).get(0).innerText; var choices = jQuery.parseJSON(json); var chosen = choices[choice]['html']; $option_set.append(chosen); } }); } });
Drupal.personalize.showChoice = function($option_set, choice) { // [Various edge case logic...] var json = $('script[type="text/template"]', $option_set).get(0).innerText; var choices = jQuery.parseJSON(json); var chosen = choices[choice]['html']; $option_set.append(chosen); }; $(document).ready(function() { if (Drupal.settings.hasOwnProperty('personalization')) { var settings = Drupal.settings.personalization; var $option_set = $(settings.selector); $.ajax({ 'url': 'http://www.my-personalization-service.com/get-decision', 'data': {'options': settings.options}, 'success': function(response) { Drupal.personalize.showChoice($option_set, response.data.choice); } }); } });
The test suite corresponds to a single html file which loads QUnit and your tests to be run.
In general, use a different suite per area of functionality being tested.
tests.js
QUnit.test( "hello test", function( assert ) { assert.ok( 1 == "1", "Passed!" ); });
QUnit will reset the elements inside the #qunit-fixture element after each test
All tests that occur after a call to QUnit.module() will be grouped into that module
QUnit.module("Tests that rely on some settings", { 'setup': function() { Drupal.settings.personalize = { 'option_sets': { 'option-set-1': { 'selector': '.some-class', } } }; }, });
Add them to your test suite
Add them to your test suite
QUnit.async()
QUnit.async()
Glad you asked! :D
Glad you asked! :D
.. and spies
.. and spies
Different types of test doubles that serve slightly different purposes
Different types of test doubles that serve slightly different purposes
A function that records arguments, return value, the value of this and exception thrown (if any) for all its calls.
A test spy can be an anonymous function or it can wrap an existing function.
Spy
// Create an anonyous spy. sinon.spy(); // Spy on a particular function. sinon.spy(myFunc); // Spy on a method of an object. sinon.spy(myObj, 'mymethod');
Spy
var myCallback = sinon.spy(); // Pass my spy to the function I'm testing. myFuncThatShouldCallMyCallback(myCallback); // Confirm my spy was called. assert(callback.called);
See http://sinonjs.org/docs/#spies for more things you can do with spies.
Use a fakeXMLHttpRequest :D
Use a fakeXMLHttpRequest :)
// Replace the native XMLHttpRequest object with Sinon's fake var xhr = sinon.useFakeXMLHttpRequest(); var requests = []; xhr.onCreate = function (request) { requests.push(request); };
Now what?
A hosted continuous integration service
A headless browser
language: php php: - 5.4 before_install: - wget https://raw.githubusercontent.com/jonkemp/qunit-phantomjs-runner/master/runner.js script: - phantomjs runner.js qunit/test.html