Front-end Automated Testing
Ruben Teijeiro
@rteijeiro
I don't know
what I like
more: Drupal
or Beer
Developers
I'm ready for
website
DevOps
Almost finished
setting up your
server. Just one
Designers
Just redesigned
the website. Now
it's shinny, edgy
and it pops!!
So,
what?
Users
Holy
shit!!
Clients
Just something
like Facebook!
We need it
yesterday...
And kitten
pics. Everyone
loves kittens!
Better in
Comic Sans
Should work
also in IE7
Front-end
Fixed
Refactoring
Fixed
Fixed
Fixed
Fixed
Fixed
Fixed
Oh
man!
And now I will
show you how it
looks like in
Now
what?
· Automated
· Repeteable
· Easy to understand
· Incremental
· Easy to run
· Fast
Unit Test
BA-K-47
Drupal Modules
· TestSwarm
https://drupal.org/project/testswarm
· FAT
· QUnit
· CasperJS
· PhantomJS
· Jasmine
TestSwarm module
FAT module
/**
* Implements hook_testswarm_tests(). */
function bacon_testswarm_tests() { 'bacon_test' => array(
'module' => 'bacon',
'description' => 'Testing bacon.', 'js' => array(
$path . '/tests/bacon.tests.js' => array(), ),
'dependencies' => array(
array('testswarm', 'jquery.simulate'), ),
'path' => 'admin/bacon/test',
'permissions' => array('test bacon') ),
}
/*global Drupal: true, jQuery: true, QUnit:true*/
(function ($, Drupal, window, document, undefined) { "use strict";
Drupal.tests.bacon = { getInfo: function() { return {
name: 'Bacon test',
description: 'Testing bacon.', group: 'Bacon'
}; },
tests: function() {
[Insert your QUnit tests here] },
};
})(jQuery, Drupal, this, this.document);
Drupal.tests.bacon = { getInfo: function() { return {
name: 'Bacon test',
description: 'Testing bacon.', group: 'Bacon'
}; },
setup: function() {
[Insert your setup code here] },
teardown: function() {
[Insert your teardown code here] },
tests: function() {
[Insert your QUnit tests here] },
};
Assert
Passes if the first argument is truthy.
var
bbq_ready
= true;
QUnit.
ok
(
bbq_ready
,
'Barbecue ready!.'
);
var bbq_ready = false;
QUnit.
ok
(
bbq_ready
,
'Barbecue ready!.'
);
ok(state, message)
equal(actual, expected, message)
Assert
Simple comparison operator (==) to compare the
actual and expected arguments.
var
bbq
= 'Bacon';
QUnit.
equal
(
bbq
,
'Bacon'
,
'Bacon barbecue!'
);
notEqual(actual, expected, message)
Assert
Simple inverted comparison operator (!=) to
compare the actual and expected arguments.
var
bbq
= 'Bacon';
QUnit.
notEqual
(
bbq
,
'Salad'
,
'No salad!'
);
var
bbq
= 'Salad';
deepEqual(actual, expected, message)
Assert
Just like equal() when comparing objects, such
that { key: value } is equal to { key: value }.
var
bbq
= {meat: 'Bacon'};
QUnit.
deepEqual
(
bbq
,
{meat: 'Bacon'}
,
'Bacon barbecue!'
);
var
bbq
= {meat: 'Chicken'};
QUnit.
deepEqual
(
bbq
,
notDeepEqual(actual, expected, message)
Assert
Just like notEqual() when comparing objects, such
that { key: value } is not equal to { key: value }.
var
bbq
= {food: 'Bacon'};
QUnit.
notDeepEqual
(
bbq
,
{food: 'Salad'}
,
'No salad!'
);
var
bbq
= {food: 'Salad'};
QUnit.
notDeepEqual
(
bbq
,
strictEqual(actual, expected, message)
Assert
Most rigid comparison of type and value with the
strict equality operator (===).
var bacon = '1';
QUnit.strictEqual(bacon, '1', 'Bacon!'); QUnit.strictEqual(bacon, 1, 'Bacon!');
notStrictEqual(actual, expected, message)
Assert
Most rigid comparison of type and value with the
strict inverted equality operator (!==).
var bacon = '1';
QUnit.notStrictEqual(bacon, 1, 'No Bacon!'); QUnit.notStrictEqual(bacon, '1', 'No Bacon!');
expect(amount)
Expect
Specify how many assertions are expected to run
within a test. If the number of assertions run does
not match the expected count, the test will fail.
var bbq = 'Bacon'; // Good
QUnit.expect(1);
QUnit.equal(bbq, 'Bacon', 'Bacon barbecue!');
// Wrong
QUnit.expect(1);
QUnit.equal(bbq, 'Bacon', 'Bacon barbecue!');
Synchronous Testing
// Number of assertions. QUnit.expect(3);
var bbq_ready = true, bbq = 'Bacon';
// Assertions.
QUnit.ok(bbq_ready, 'Barbacue is ready!');
QUnit.equal(bbq, 'Bacon', 'Bacon barbecue!'); QUnit.notEqual(bbq, 'Salad', 'No salad!');
Asynchronous Testing
QUnit.expect(2);
var bbq_ready = false, bbq = 'Bacon',
time = 36000; // Miliseconds.
QUnit.stop();
setTimeout(function() { bbq_ready = true;
QUnit.ok(bbq_ready, 'Barbacue is ready!'); QUnit.start();
}, time);
Testing User Actions
/** * Implements hook_testswarm_tests(). */ function bacon_testswarm_tests() { 'bacon_test' => array( 'module' => 'bacon','description' => 'Testing bacon.', 'js' => array(
$path . '/tests/bacon.tests.js' => array(), ),
'dependencies' => array(
array('testswarm', 'jquery.simulate'), ),
'path' => 'admin/bacon/test',
'permissions' => array('test bacon') ),
Testing User Actions
QUnit.expect(1);
var bbq_ready = false, bbq = 'Bacon';
bbq_ready.trigger('change');
QUnit.ok(bbq_ready, 'Barbecue ready!');
Questions
?