JavaScript Unit Testing
2012 Mats Bryntse
@bryntum
var me = {
name : ”Mats Bryntse”,
age : 35,
from : ”Helsingborg, Sweden”,
does : ”Runs Bryntum”,
site : ” www.bryntum.com”...
What we do
JavaScript scheduling
and Gantt charts
Siesta (JS Test Tool)
</SELFPROMOTION>
First, a quick survey:
How many of you...
• have a web application a frontend test suite?
• have frontend test suite as part of your CI proc.
• run your test suite ...
Unit test JS, really?? But...
”... my code is bug free”
”...testing takes time away from
adding new features (+ new bugs)”...
Reasons for testing
JavaScript
A typical web app...
Interwebs
http://www.app.com
The backend
• Single controlled platform
• Simple to test and refactor
• Good IDEs and tools
C#
Java
PHP
The frontend
• Multiple platforms & versions
(Mac, Windows XP/Vista/7, Linux...)
• Multiple browser versions
• Hard to ref...
Conclusion
• Developing frontend code is harder than
developing server code.
• Mainly due to lack of good tools
• Lots of ...
As good JS dev tools are hard to find, we need to
make good use of existing tools and practices.
Reasons for testing
JavaScript contd.
Easy to introduce
unforeseen errors
isUserCrazy: function(user, isAdmin) {
// DON’T CHANGE THIS
if (user.age > 35 &&
isAdm...
Refactoring is painful
0
20
40
60
80
100
120
Pain of Refactoring
Backend
Frontend
X-browser testing doesn’t
scale
• iOS
• Android
• IE Mobile
• Blackberry
• Firefox mobile
• ...
Efficient debugging
• We spend lots of time debugging frontend
code.
• Helpful to know which parts of an application
is we...
Additional benefits of
testing
• Find bugs early
• Develop & refactor with confidence
• Tests serve as additional API docu...
Code handover
• Test cases can be immensely useful when
handing over responsibility for a JS module
• Developer Bob quits ...
New guy studies codebase
/* I am not sure if we need this, but too scared to delete. */
// drunk, fix later
// TODO make t...
Code handover
New guy, scared
Code handover
• Without test suite, new guy will be afraid to
make any major changes.
• Only minor cosmetic changes on the...
So, how do I start..?
• Code and design for testability
• Choose the tools to help you
• Automation / CI / Coverage
Writing testable JS
• Keep your JavaScript in JS files
• Never put JavaScript in your HTML
page/tags
• Keep code organized...
Writing testable JS
Writing testable JS
• Fat model, skinny view
• Don’t pollute your views with business logic
• Testing pure JS is a lot eas...
Writing testable JS
Ext.define('UserForm', {
extend: 'Ext.FormPanel',
width: 400,
height: 400,
model: new UserModel(),
// ...
Writing testable JS
Ext.define('UserModel', {
extend: 'Ext.data.Model',
name : “”,
password : “”,
// Returns array of User...
Writing testable JS
Ext.define('UserForm', {
extend: 'Ext.FormPanel',
width: 400,
height: 400,
model: new UserModel(),
// ...
Avoid private code
• Avoid overuse of private functions in
closures
• If your code cannot be accessed it cannot
be tested
Tools
Choose your tools
• Last few years has brought numerous new
testing tools to the JavaScript world
• Quite hard to know whi...
Unit Test Tools
• Jasmine
• Siesta
• Buster.js (beta) / Sinon.js
• DOH (Dojo Object Harness)
• Qunit (jQuery)
• JsUnit (ab...
Pure JS Test Tools
• More or less similar approach in most tools
• Define HTML/JS harness, and test suites is
composed by ...
Jasmine
• Simple DOM-less testing
• BDD syntax
• Borrows “the best parts” of ScrewUnit,
JSSpec, JSpec, and RSpec.
Anatomy of a Jasmine test
describe('panda', function () {
it('is happy', function () {
expect(panda).toBe('happy');
});
})...
Jasmine matchers
Siesta
• Unit testing and functional DOM testing
• Simple TDD syntax
• Test any JS: Ext JS, jQuery, NodeJS etc.
• Automate...
Anatomy of a Siesta test
StartTest(function(t) {
t.diag('Testing jQuery...');
$('body').html('JQuery was here');
t.content...
Testing Ajax
Testing Ajax
• Try to avoid calling your actual server.
• Use either static JS files with mock data
(async, slower)
• Or M...
Testing Ajax w/ Jasmine
it("should make an AJAX request to the correct URL", function() {
spyOn($, "ajax");
getProduct(123...
Functional testing
• Test larger piece of your app, or the
application as a whole.
• Simulate user interaction, click, typ...
Functional testing tools
• Selenium
• Funcunit
• JsTestDriver
• Siesta
• Watir
• DOH Robot (Dojo)
• Sahi
• Squish (Frog Lo...
Interacting with the DOM
Two main approaches of faking a user
• Synthetic events
• Native events (via Java Applet)
Synthetic events
+ Supported in all major browsers
+ Compatible with mobile
+ Don’t rely on native event queue
Tests can b...
Native events
+ Java applets are supported in all desktop
browsers
+ As close to a ’real’ user as possible
- Won’t work on...
”Browser Drivers”
Opens real browser instances and ’drives’
them
Outputs commands and evaluates result
Can be quite slow
”Browser Drivers”
Selenium
The most widely used functional testing tool. Firefox Recorder.
JsTestDriver
By Google. ”Remote...
Headless browsers
• “A web browser without a graphical user
interface”
• Command line interface
• Great for automating tes...
Headless browsers
+ Run tests on command line
+ Faster
+ Automation
+ Doesn’t require an actual browser
- Not 100% accurat...
Headless browsers
PhantomJS (headless WebKit + JavaScript API)
env.js(Runs on Rhino)
JsDom (CommonJS implementation of the...
Phantom JS
Created by Ariya Hidayat (Sencha Inc.)
Fast headless testing
Site scraping
SVG rendering
Supports CoffeeScript
JS Code Coverage
• JsCoverage
Seems abandoned
• ScriptCover
Google Chrome Plugin
• JsTestDriver
Add-in module for coverage...
Continuous Integration
• Once you have decided on your testing
toolset, integrate it into your CI.
• Automatically run tes...
CI Tools
• Jenkins
• Cruise Control
• Test Swarm
So which tools are
right for me?
Evaluating tools
• Some are geared towards specific server side
languages, Java/Ruby/C#
• Prototype and find what works be...
Resources
http://www.adequatelygood.com/2010/7/Writing-Testable-JavaScript
http://blog.jcoglan.com/2011/07/14/refactoring-...
Resources - Yahoo
http://screen.yahoo.com/
Resources - GTAC
Finally: wise words
”Without unit tests, you’re not
refactoring. You’re just changing
shit.”
Hamlet D’Arcy
That’s all folks!
Questions?
2012 Mats Bryntse
@bryntum
Upcoming SlideShare
Loading in...5
×

Java script unit testing

4,198

Published on

My talk at Community Day in Stockholm.

Published in: Technology
0 Comments
4 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
4,198
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
78
Comments
0
Likes
4
Embeds 0
No embeds

No notes for slide

Java script unit testing

  1. 1. JavaScript Unit Testing 2012 Mats Bryntse @bryntum
  2. 2. var me = { name : ”Mats Bryntse”, age : 35, from : ”Helsingborg, Sweden”, does : ”Runs Bryntum”, site : ” www.bryntum.com”, twitter : ”@bryntum”, likes : ”Ext JS” }; About me
  3. 3. What we do JavaScript scheduling and Gantt charts Siesta (JS Test Tool)
  4. 4. </SELFPROMOTION>
  5. 5. First, a quick survey: How many of you...
  6. 6. • have a web application a frontend test suite? • have frontend test suite as part of your CI proc. • run your test suite in all major browsers? • have zero or less frontend tests for your app. How many of you...
  7. 7. Unit test JS, really?? But... ”... my code is bug free” ”...testing takes time away from adding new features (+ new bugs)” ”...it’s QA’s job to test” ”... it’s boring and I’ll quit my job”
  8. 8. Reasons for testing JavaScript
  9. 9. A typical web app... Interwebs http://www.app.com
  10. 10. The backend • Single controlled platform • Simple to test and refactor • Good IDEs and tools C# Java PHP
  11. 11. The frontend • Multiple platforms & versions (Mac, Windows XP/Vista/7, Linux...) • Multiple browser versions • Hard to refactor • JavaScript support in IDEs is still !== awesome
  12. 12. Conclusion • Developing frontend code is harder than developing server code. • Mainly due to lack of good tools • Lots of uncertainty, x-browser issues • IE6
  13. 13. As good JS dev tools are hard to find, we need to make good use of existing tools and practices.
  14. 14. Reasons for testing JavaScript contd.
  15. 15. Easy to introduce unforeseen errors isUserCrazy: function(user, isAdmin) { // DON’T CHANGE THIS if (user.age > 35 && isAdmin!== true && isAdmin!== false) { user.crazy = true; } }
  16. 16. Refactoring is painful 0 20 40 60 80 100 120 Pain of Refactoring Backend Frontend
  17. 17. X-browser testing doesn’t scale • iOS • Android • IE Mobile • Blackberry • Firefox mobile • ...
  18. 18. Efficient debugging • We spend lots of time debugging frontend code. • Helpful to know which parts of an application is well tested => less likely to have bugs.
  19. 19. Additional benefits of testing • Find bugs early • Develop & refactor with confidence • Tests serve as additional API documentation • Helps you detect tightly coupled code
  20. 20. Code handover • Test cases can be immensely useful when handing over responsibility for a JS module • Developer Bob quits his job. New guy gets responsibility of his JS code. • How will the new guy know what parts of the codebase safe to change & refactor?
  21. 21. New guy studies codebase /* I am not sure if we need this, but too scared to delete. */ // drunk, fix later // TODO make this work /** * When I wrote this, only God and I understood what I was doing * Now, God only knows **/ scripts/core/application.js
  22. 22. Code handover New guy, scared
  23. 23. Code handover • Without test suite, new guy will be afraid to make any major changes. • Only minor cosmetic changes on the surface. • System accumulates cruft over time. • Sounds familiar?
  24. 24. So, how do I start..? • Code and design for testability • Choose the tools to help you • Automation / CI / Coverage
  25. 25. Writing testable JS • Keep your JavaScript in JS files • Never put JavaScript in your HTML page/tags • Keep code organized in logical manageable files. Decide on some max nbr of lines/file.
  26. 26. Writing testable JS
  27. 27. Writing testable JS • Fat model, skinny view • Don’t pollute your views with business logic • Testing pure JS is a lot easier than testing DOM-dependent JS • Promotes reuse of your code
  28. 28. Writing testable JS Ext.define('UserForm', { extend: 'Ext.FormPanel', width: 400, height: 400, model: new UserModel(), // Returns true if User is valid isValid: function (userModel) { return userModel.name.length > 4 && userModel.password.length > 8; } }); Mixing view and business logic
  29. 29. Writing testable JS Ext.define('UserModel', { extend: 'Ext.data.Model', name : “”, password : “”, // Returns array of User model objects isValid : function () { return this.name.length > 4 && this.password.length > 8; } }); Better:
  30. 30. Writing testable JS Ext.define('UserForm', { extend: 'Ext.FormPanel', width: 400, height: 400, model: new UserModel(), // Returns true if User is valid isValid: function (userModel) { return userModel.isValid(); } }); No business logic in view
  31. 31. Avoid private code • Avoid overuse of private functions in closures • If your code cannot be accessed it cannot be tested
  32. 32. Tools
  33. 33. Choose your tools • Last few years has brought numerous new testing tools to the JavaScript world • Quite hard to know which to choose, evaluation needed • Positive trend, lots of buzz around web testing
  34. 34. Unit Test Tools • Jasmine • Siesta • Buster.js (beta) / Sinon.js • DOH (Dojo Object Harness) • Qunit (jQuery) • JsUnit (abandoned?) • YUI Test • Google js-test • Zombie (headless/Node)
  35. 35. Pure JS Test Tools • More or less similar approach in most tools • Define HTML/JS harness, and test suites is composed by single JS test files. • Some support/require setup/tearDown • Others rely on iframes, slower though no cleanup required
  36. 36. Jasmine • Simple DOM-less testing • BDD syntax • Borrows “the best parts” of ScrewUnit, JSSpec, JSpec, and RSpec.
  37. 37. Anatomy of a Jasmine test describe('panda', function () { it('is happy', function () { expect(panda).toBe('happy'); }); }); Suite / Spec Source panda = 'happy'; // => PASS
  38. 38. Jasmine matchers
  39. 39. Siesta • Unit testing and functional DOM testing • Simple TDD syntax • Test any JS: Ext JS, jQuery, NodeJS etc. • Automate using PhantomJS & Selenium. • Extensible, easy to add own assertion methods
  40. 40. Anatomy of a Siesta test StartTest(function(t) { t.diag('Testing jQuery...'); $('body').html('JQuery was here'); t.contentLike(document.body, 'JQuery was here', 'Found correct text in DOM'); }); test-jquery_01.js
  41. 41. Testing Ajax
  42. 42. Testing Ajax • Try to avoid calling your actual server. • Use either static JS files with mock data (async, slower) • Or Mock the entire Ajax call (sync, faster) Sinon.js, Jasmine-ajax etc.
  43. 43. Testing Ajax w/ Jasmine it("should make an AJAX request to the correct URL", function() { spyOn($, "ajax"); getProduct(123); expect($.ajax.mostRecentCall.args[0]["url"]).toEqual("/products/123"); }); function getProduct(id) { $.ajax({ type: "GET", url: "/products/" + id, dataType: "json" }); }
  44. 44. Functional testing • Test larger piece of your app, or the application as a whole. • Simulate user interaction, click, type etc. • Navigate between pages
  45. 45. Functional testing tools • Selenium • Funcunit • JsTestDriver • Siesta • Watir • DOH Robot (Dojo) • Sahi • Squish (Frog Logic)
  46. 46. Interacting with the DOM Two main approaches of faking a user • Synthetic events • Native events (via Java Applet)
  47. 47. Synthetic events + Supported in all major browsers + Compatible with mobile + Don’t rely on native event queue Tests can be run in parallell. - Browsers don’t ”trust” synthetic events - Enter key on a focused link - Tab between input fields, etc... - X-browser differences DOM Events, Key events, key codes (http://unixpapa.com)
  48. 48. Native events + Java applets are supported in all desktop browsers + As close to a ’real’ user as possible - Won’t work on iOS, Android. - No parallell tests since native event queue is used.
  49. 49. ”Browser Drivers” Opens real browser instances and ’drives’ them Outputs commands and evaluates result Can be quite slow
  50. 50. ”Browser Drivers” Selenium The most widely used functional testing tool. Firefox Recorder. JsTestDriver By Google. ”Remote JavaScript Console”. IntelliJ and Eclipse Watir Web Application Testing in Ruby. Also a .NET port, WatiN. Sahi By TytoSoftware. Has X-browser recorder.
  51. 51. Headless browsers • “A web browser without a graphical user interface” • Command line interface • Great for automating tests, integrating with CI tools (Jenkins, Cruise Control…)
  52. 52. Headless browsers + Run tests on command line + Faster + Automation + Doesn’t require an actual browser - Not 100% accurate, but close.
  53. 53. Headless browsers PhantomJS (headless WebKit + JavaScript API) env.js(Runs on Rhino) JsDom (CommonJS implementation of the DOM)
  54. 54. Phantom JS Created by Ariya Hidayat (Sencha Inc.) Fast headless testing Site scraping SVG rendering Supports CoffeeScript
  55. 55. JS Code Coverage • JsCoverage Seems abandoned • ScriptCover Google Chrome Plugin • JsTestDriver Add-in module for coverage • JesCov Rhino, Jasmine
  56. 56. Continuous Integration • Once you have decided on your testing toolset, integrate it into your CI. • Automatically run test suite on pre-commit or post-commit • Nightly build, full test suite execution, reporting via email, or other CI systems.
  57. 57. CI Tools • Jenkins • Cruise Control • Test Swarm
  58. 58. So which tools are right for me?
  59. 59. Evaluating tools • Some are geared towards specific server side languages, Java/Ruby/C# • Prototype and find what works best for you • Make sure the tool you use integrates nicely with your IDE and CI-environment
  60. 60. Resources http://www.adequatelygood.com/2010/7/Writing-Testable-JavaScript http://blog.jcoglan.com/2011/07/14/refactoring-towards-testable-javascript-part-1/
  61. 61. Resources - Yahoo http://screen.yahoo.com/
  62. 62. Resources - GTAC
  63. 63. Finally: wise words ”Without unit tests, you’re not refactoring. You’re just changing shit.” Hamlet D’Arcy
  64. 64. That’s all folks! Questions? 2012 Mats Bryntse @bryntum
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×