The document discusses unit testing and test-driven development. It introduces the QUnit JavaScript testing framework, describing how to write tests and assertions using its API. Key aspects covered include setting up QUnit, the test and assert functions, asynchronous testing, grouping tests into modules, and integrating automated testing with Node and Grunt.
2. Points to Discuss
Unit Testing & Test Driven Development
QUnit
QUnit API
Automated Testing (a brief introduction)
3. Unit Testing
In computer programming, unit testing is a procedure
used to validate that individual modules or units of
source code are working properly.
Unit testing is used for
(i) Test Driven Development
(ii) Fixing bugs
(iii) Regression testing
4. Test Driven Development
Test-Driven Development (TDD) is a computer
programming technique that involves repeatedly first
writing a test case and then implementing only the code
necessary to pass the test.
Test-driven development is a method of designing
software, not merely a method of testing.
7. What do you need?
A Unit Testing framework
Development Environment
8. QUnit
QUnit is a powerful, easy-to-use JavaScript unit testing
framework.
It's used by the jQuery, jQuery UI and jQuery Mobile
projects and is capable of testing any generic JavaScript
code, including itself!
Supports the same browsers as jQuery 1.x. That's IE6+
and Current - 1 for Chrome, Firefox, Safari and Opera.
9. Getting Started
Just qunit.js, qunit.css, and a little bit of HTML
A Quick Demo:
http://jsfiddle.net/akankshaaro/rq31v84h/
11. Test : QUnit.test( name, test )
Adds a test to run.
Testing the most common, synchronous code
Qunit.test(name of the test, function() {
//write down the assertions
});
function: Function to close over assertions
12. Test : 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.
test(expected assertions", function() {
expect( 2 );
//two assertions are expected
});
13. Asserts
ok
Equal
notEqual
strictEqual
notStrictEqual
deepEqual
notDeepEqual
throws
14. Assert - ok()
ok( state, message )
A boolean check, passes if the first argument is truthy.
test("ok, function() {
expect(3);
ok(true, "passes because true is true");
ok(1, "passes because 1 is truthy");
ok("", "fails because empty string is not truthy");
});
15. Assert - equal()
equal( actual, expected, message )
A comparison assertion that passes if actual == expected.
test("equal, function() {
expect(3);
var actual = 5 - 4;
equal(actual, 1, "passes because 1 == 1");
equal(actual, true, "passes because 1 == true");
equal(actual, false, "fails because 1 != false");
});
16. Assert - notEqual()
notEqual( actual, expected, message )
A comparison assertion that passes if actual != expected.
test("notEqual, function() {
expect(3);
var actual = 5 - 4;
notEqual(actual, 0, "passes because 1 != 0");
notEqual(actual, false, "passes because 1 != false");
notEqual(actual, true, "fails because 1 == true");
});
17. Assert - strictEqual()
strictEqual( actual, expected, message )
A comparison assertion that passes if actual === expected.
test("notEqual, function() {
expect(3);
var actual = 5 - 4;
strictEqual(actual, 1, "passes because 1 === 1");
strictEqual(actual, true, "fails because 1 !== true");
strictEqual(actual, false, "fails because 1 !== false");
});
18. Assert - notStrictEqual()
notStrictEqual( actual, expected, message )
A comparison assertion that passes if actual !== expected.
test("notStrictEqual, function() {
expect(3);
var actual = 5 - 4;
notStrictEqual(actual, 1, "fails because 1 === 1");
notStrictEqual(actual, true, "passes because 1 !== true");
notStrictEqual(actual, false, "passes because 1 !== false");
});
19. Assert - deepEqual ()
deepEqual( actual, expected, message )
Recursive comparison assertion, working on primitives,
arrays and objects, using ===.
test("deepEqual, function() {
expect(3);
var actual = {a: 1};
equal( actual, {a: 1}, "fails because objects are different");
deepEqual(actual, {a: 1}, "passes because objects are equivalent");
deepEqual(actual, {a: "1"}, "fails because '1' !== 1");
});
20. Assert - notDeepEqual()
notDeepEqual( actual, expected, message )
Recursive comparison assertion. The result of deepEqual,
inverted.
test("notDeepEqual, function() {
expect(3);
var actual = {a: 1};
notEqual( actual, {a: 1}, "passes because objects are different");
notDeepEqual(actual, {a: 1}, "fails because objects are equivalent");
notDeepEqual(actual, {a: "1"}, "passes because '1' !== 1");
});
21. Assert - throws()
Assertion to test if a callback throws an exception when
run and optionally compare the thrown error.
test("throws, function() {
expect(3);
throws(
function() { throw new Error("Look me, I'm an error!"); },
"passes because an error is thrown inside the callback
);
throws(
function() { x // ReferenceError: x is not defined },
"passes because an error is thrown inside the callback
);
throws (
function() { var a = 1; },
"fails because no error is thrown inside the callback
);
});
22. Tests Should be Atomic
Execution order cannot be guaranteed!
Each test should be independent from one another.
QUnit.test() is used to keep test cases atomic.
23. Async Control : QUnit.asyncTest
For testing asynchronous code, QUnit.asyncTest will
automatically stop the test runner and wait for your code
to call QUnit.start() to continue.
The following illustrates an asynchronous test that waits 1
second before resuming
QUnit.asyncTest( "asynchronous test: one second later!", function(
assert ) {
expect( 1 );
setTimeout(function() {
assert.ok( true, "Passed and ready to resume!" );
QUnit.start(); }, 1000);
});
24. Async Control : QUnit.stop()
Increase the number of QUnit.start() calls the testrunner
should wait for before continuing.
When your async test has multiple exit points, call
QUnit.stop() multiple times or use the increment
argument.
QUnit.test( "a test", function( assert ){
QUnit.stop();
setTimeout(function(){
assert.equals("somedata" , "someExpectedValue" );
QUnit.start(); }, 150 );
});
25. Grouping Tests : QUnit.module()
It groups tests together to keep them logically organized
and be able to run a specific group of tests on their own.
All tests that occur after a call to QUnit.module() will be
grouped into that module. The test names will all be
preceded by the module name in the test results.
QUnit.module( "group a" );//tests for module a
QUnit.module( "group b" );//test for module b
26. Grouping Tests : QUnit.module()
QUnit.module() can also be used to extract common code
from tests within that module.
The QUnit.module() function takes an optional second
parameter to define functions to run before and after
each test within the module
QUnit.module( "module", {
setup: function( assert )
{//any setup task},
teardown: function( assert )
{//task to be performed after test completion}
});
QUnit.test( "test with setup and teardown", function()
{
//test cases
});
27. Callbacks
When integrating QUnit into other tools like CI servers,
use these callbacks as an API to read test results.
QUnit.begin()
QUnit.done()
QUnit.moduleStart()
QUnit.moduleDone()
QUnit.testStart()
QUnit.testDone()
30. Automated Testing
Install Node
Using Node Package Manager install Grunt
Install QUnit module to your project directory(npm install
qunit)
project
src // plugin source, project files, etc
tests // we'll be working in here mostly
lib
jquery-1.x.x.min.js // if you need it (QUnit doesn't)
qunit-1.10.0.js
qunit-1.10.0.css
index.html // our QUnit test specification
tests.js // your tests (could be split into multiple files)
Gruntfile.js // you'll create this, we'll get to it shortly
package.json // to specify our project dependencies