First steps towards Javascript testing
Posted: - Modified: | development, geekI know, I know, it's about time I got the hang of this. Better late than never, right? =) Anyway, I spent some time going through tutorials for QUnit and Jasmine. For QUnit, I followed this Smashing Magazine tutorial on Javascript unit testing. I modified the code a little bit to add the Z timezone to the test data, since my tests initially didn't pass.
test.html
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Refactored date examples</title> <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.15.0.css" /> <script src="http://code.jquery.com/qunit/qunit-1.15.0.js"></script> <script src="prettydate.js"></script> <script> test("prettydate.format", function() { function date(then, expected) { equal(prettyDate.format('2008/01/28 22:25:00Z', then), expected); } date("2008/01/28 22:24:30Z", "just now"); date("2008/01/28 22:23:30Z", "1 minute ago"); date("2008/01/28 21:23:30Z", "1 hour ago"); date("2008/01/27 22:23:30Z", "Yesterday"); date("2008/01/26 22:23:30Z", "2 days ago"); date("2007/01/26 22:23:30Z", undefined); }); function domtest(name, now, first, second) { test(name, function() { var links = document.getElementById('qunit-fixture').getElementsByTagName('a'); equal(links[0].innerHTML, 'January 28th, 2008'); equal(links[2].innerHTML, 'January 27th, 2008'); prettyDate.update(now); equal(links[0].innerHTML, first); equal(links[2].innerHTML, second); }); } domtest("prettyDate.update", '2008-01-28T22:25:00Z', '2 hours ago', 'Yesterday'); domtest("prettyDate.update, one day later", '2008-01-29T22:25:00Z', 'Yesterday', '2 days ago'); </script> </head> <body> <div id="qunit"></div> <div id="qunit-fixture"> <ul> <li class="entry" id="post57"> <p>blah blah blah…</p> <small class="extra"> Posted <span class="time"><a href="/2008/01/blah/57/" title="2008-01-28T20:24:17Z">January 28th, 2008</a></span> by <span class="author"><a href="/john/">John Resig</a></span> </small> </li> <li class="entry" id="post57"> <p>blah blah blah…</p> <small class="extra"> Posted <span class="time"><a href="/2008/01/blah/57/" title="2008-01-27T22:24:17Z">January 27th, 2008</a></span> by <span class="author"><a href="/john/">John Resig</a></span> </small> </li> </ul> </div> </body> </html>
For practice, I converted the QUnit tests to Jasmine. The first part of the test was easy, but I wanted a clean way to do the HTML fixture-based tests for prettydate.update too. Jasmine-JQuery gives you a handy way to have HTML fixtures. Here's what my code ended up as:
spec/DateSpec.js
describe("PrettyDate.format", function() { function checkDate(name, then, expected) { it(name, function() { expect(prettyDate.format('2008/01/28 22:25:00Z', then)).toEqual(expected); }); } checkDate("should display recent times", '2008/01/28 22:24:30Z', 'just now'); checkDate("should display times within a minute", '2008/01/28 22:23:30Z', '1 minute ago'); checkDate("should display times within an hour", '2008/01/28 21:23:30Z', '1 hour ago'); checkDate("should display times within a day", '2008/01/27 22:23:30Z', 'Yesterday'); checkDate("should display times within two days", '2008/01/26 22:23:30Z', '2 days ago'); }); describe("PrettyDate.update", function() { function domtest(name, now, first, second) { it(name, function() { loadFixtures('test_fixture.html'); var links = document.getElementById('qunit-fixture').getElementsByTagName('a'); expect(links[0].innerHTML).toEqual('January 28th, 2008'); expect(links[2].innerHTML).toEqual('January 27th, 2008'); prettyDate.update(now); expect(links[0].innerHTML).toEqual(first); expect(links[2].innerHTML).toEqual(second); }); } domtest("prettyDate.update", '2008-01-28T22:25:00Z', '2 hours ago', 'Yesterday'); domtest("prettyDate.update, one day later", '2008-01-29T22:25:00Z', 'Yesterday', '2 days ago'); });
jasmine.html
<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Jasmine Spec Runner v2.0.2</title> <link rel="shortcut icon" type="image/png" href="lib/jasmine-2.0.2/jasmine_favicon.png"> <link rel="stylesheet" type="text/css" href="lib/jasmine-2.0.2/jasmine.css"> <script type="text/javascript" src="https://code.jquery.com/jquery-2.1.1.min.js"></script> <script type="text/javascript" src="lib/jasmine-2.0.2/jasmine.js"></script> <script type="text/javascript" src="lib/jasmine-2.0.2/jasmine-html.js"></script> <script type="text/javascript" src="lib/jasmine-2.0.2/boot.js"></script> <script type="text/javascript" src="jasmine-jquery.js"></script> <!-- include source files here... --> <script type="text/javascript" src="prettydate.js"></script> <!-- include spec files here... --> <script type="text/javascript" src="spec/DateSpec.js"></script> </head> <body> </body> </html>
I'm looking forward to learning how to use Jasmine to test Angular applications, since behaviour-driven testing seems to be common practice there. Little steps! =)