20. Karma Getting Started
# run just once to install
npm install karma -g
# create a project directory
mkdir myproject
cd myproject
# create karma configuration file
karma init
21. Karma Config
• Just a JavaScript file
• keys determine how test should run
22. Karma Config
• files is a list of JS files to include in the test
• Can use wildcards
29. Agenda
• Flow control: before, after, beforeEach,
afterEach
• Writing async tests
• Fixtures and DOM testing
30. Let’s Flow
describe('Test 1', function() {
it('should do X', function() {
var p1 = new Player('bob');
var p2 = new Player('John');
var game = new GameEngine(p1, p2);
// test stuff with game
});
it('should do Y', function() {
var p1 = new Player('bob');
var p2 = new Player('John');
var game = new GameEngine(p1, p2);
// test stuff with game
});
});
31. Let’s Flow
describe('Test 1', function() {
it('should do X', function() {
var p1 = new Player('bob');
var p2 = new Player('John');
var game = new GameEngine(p1, p2);
// test stuff with game
});
it('should do Y', function() {
var p1 = new Player('bob');
var p2 = new Player('John');
var game = new GameEngine(p1, p2);
// test stuff with game
});
});
Same code...
32. A Better Scheme
•
beforeEach() runs
before each test
•
also has:
•
•
afterEach() for
cleanups
describe('Test 1', function() {!
var game;!
!
beforeEach(function() {!
var p1 = new Player('bob');!
var p2 = new Player('John');!
game = new GameEngine(p1, p2);!
});!
!
it('should do X', function() {!
// test stuff with game!
});!
!
before() and
after() run once
in the suite
!
it('should do Y', function() {!
// test stuff with game!
});!
});
37. Async Code
describe('Test 1', function() {
it('should do wait', function(done) {
setTimeout(function() {
// now we can test result
assert(true);
done();
}, 1000);
});
});
38. Async Code
Taking a function
argument tells
mocha the test will
only end after it’s
called
describe('Test 1', function() {
it('should do wait', function(done) {
setTimeout(function() {
// now we can test result
assert(true);
done();
}, 1000);
});
});
39. Async Code
Calling the callback
ends the test
describe('Test 1', function() {
it('should do wait', function(done) {
setTimeout(function() {
// now we can test result
assert(true);
done();
}, 1000);
});
});
40. Async Notes
• Always call done() or your test will fail on
timeout
• Default timeout is 2 seconds
41. Controlling Timeouts
describe('Test 1', function() {
// set suite specific timeout
this.timeout(500);
it('should do wait', function(done) {
// test specific timeout
this.timeout(2000);
});
});
42. Same goes for Ajax
describe('Test 1', function() {
// set suite specific timeout
this.timeout(5000);
it('should get user photo', function(done) {
$.get('profile.png', function(data) {
// run tests on data
done();
});
});
});
48. Almost Ready
• HTML files are not served by default
• We need to tell karma to serve it
49. Serving HTMLs
• Modify files section to include the last
(HTML) pattern
// list of files / patterns to load in the browser
files: [
'lib/**/*.js',
'plugins/**/*.js',
'test/fixtures/*.html',
'spec/*.js'
],
50. Testing a jQuery Plugin
it('should change the header text lowercase', function() {
$('.truncate').succinct({ size: 100 });
!
var result = $('.truncate').text();
assert.equal( result.length , 100 );
});
51. Fixtures & DOM
• Define DOM fragments in HTML files
• Load from test suite
• Test and clean up
84. Let’s write a test for the following class
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
function Person(id) {
var self = this;
self.load = function() {
var url = '/users/' + id;
$.get('/users/' + id, function(info) {
self.name = info.name;
self.favorite_color = info.favorite_color;
});
};
}
85. Testing Plan
• Set-up a fake server
• Create a new Person
• call load()
• verify fields data
86. Setting Up The Server
1.
2.
3.
4.
5.
6.
7.
8.
9.
var server = sinon.fakeServer.create();
var headers = {"Content-Type" : "application/json"};
var response = JSON.stringify(
{"name" : "joe", "favorite_color": "blue" });
server.respondWith("GET", "/users/7",
[200, headers, response]);
// now requesting /user/info.php returns joe's info as a JSON
87. Loading a Person
1.
2.
3.
4.
5.
6.
var p = new Person(7);
// sends a request
p.load();
// now we have 1 pending request, let's fake the response
server.respond();
88. Verifying the Data
1.
2.
3.
4.
5.
6.
// finally, verify data
expect(p.name).to.eq('joe');
expect(p.favorite_color).to.eq('blue');
// and restore AJAX behavior
server.restore();
89. Fake Server
• Use respondWith() to set up routes
• Use respond() to send the response
90. Fake Server
• Regexps are also supported, so this works:
1.
2.
3.
4.
5.
6.
server.respondWith(//todo-items/(d+)/, function (xhr, id) {
xhr.respond(
200,
{ "Content-Type": "application/json" },
'[{ "id": ' + id + ' }]');
});
91. Fake Server
• For fine grained control, consider fake
XMLHttpRequest
• http://sinonjs.org/docs/#server