java script unit testing
DESCRIPTION
My talk at Community Day in Stockholm.TRANSCRIPT
![Page 1: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/1.jpg)
JavaScript Unit Testing
2012 Mats Bryntse@bryntum
![Page 2: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/2.jpg)
var me = { name : ”Mats Bryntse”, age : 35, from : ”Helsingborg, Sweden”, does : ”Runs Bryntum”, site : ” www.bryntum.com”, twitter : ”@bryntum”, likes : ”Ext JS”};
About me
![Page 3: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/3.jpg)
What we do
JavaScript scheduling and Gantt charts
Siesta (JS Test Tool)
![Page 4: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/4.jpg)
</SELFPROMOTION>
![Page 5: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/5.jpg)
First, a quick survey:
How many of you...
![Page 6: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/6.jpg)
• 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...
![Page 7: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/7.jpg)
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”
![Page 8: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/8.jpg)
Reasons for testing JavaScript
![Page 9: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/9.jpg)
A typical web app...
Interwebs
http://www.app.com
![Page 10: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/10.jpg)
The backend
• Single controlled platform
• Simple to test and refactor
• Good IDEs and tools
C#Java
PHP
![Page 11: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/11.jpg)
The frontend
• Multiple platforms & versions (Mac, Windows XP/Vista/7, Linux...)
• Multiple browser versions
• Hard to refactor
• JavaScript support in IDEs is still !== awesome
![Page 12: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/12.jpg)
Conclusion
• Developing frontend code is harder than developing server code.
• Mainly due to lack of good tools
• Lots of uncertainty, x-browser issues
• IE6
![Page 13: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/13.jpg)
As good JS dev tools are hard to find, we need to make good use of existing tools and practices.
![Page 14: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/14.jpg)
Reasons for testing JavaScript contd.
![Page 15: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/15.jpg)
Easy to introduce unforeseen errors
isUserCrazy: function(user, isAdmin) {
// DON’T CHANGE THIS if (user.age > 35 &&
isAdmin!== true && isAdmin!== false) {
user.crazy = true;}
}
![Page 16: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/16.jpg)
Refactoring is painful
Pain of Refactoring0
20
40
60
80
100
120
BackendFrontend
![Page 17: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/17.jpg)
X-browser testing doesn’t scale
• iOS• Android• IE Mobile• Blackberry• Firefox mobile• ...
![Page 18: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/18.jpg)
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.
![Page 19: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/19.jpg)
Additional benefits of testing
• Find bugs early
• Develop & refactor with confidence
• Tests serve as additional API documentation
• Helps you detect tightly coupled code
![Page 20: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/20.jpg)
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?
![Page 21: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/21.jpg)
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
![Page 22: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/22.jpg)
Code handover
New guy, scared
![Page 23: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/23.jpg)
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?
![Page 24: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/24.jpg)
So, how do I start..?
• Code and design for testability
• Choose the tools to help you
• Automation / CI / Coverage
![Page 25: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/25.jpg)
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.
![Page 26: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/26.jpg)
Writing testable JS
![Page 27: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/27.jpg)
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
![Page 28: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/28.jpg)
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
![Page 29: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/29.jpg)
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:
![Page 30: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/30.jpg)
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
![Page 31: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/31.jpg)
Avoid private code
• Avoid overuse of private functions in closures
• If your code cannot be accessed it cannot be tested
![Page 32: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/32.jpg)
Tools
![Page 33: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/33.jpg)
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
![Page 34: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/34.jpg)
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)
![Page 35: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/35.jpg)
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
![Page 36: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/36.jpg)
Jasmine
• Simple DOM-less testing
• BDD syntax
• Borrows “the best parts” of ScrewUnit, JSSpec, JSpec, and RSpec.
![Page 37: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/37.jpg)
Anatomy of a Jasmine test
describe('panda', function () { it('is happy', function () { expect(panda).toBe('happy'); });});
Suite / Spec
Sourcepanda = 'happy'; // => PASS
![Page 38: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/38.jpg)
Jasmine matchers
![Page 39: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/39.jpg)
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
![Page 40: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/40.jpg)
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
![Page 41: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/41.jpg)
Testing Ajax
![Page 42: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/42.jpg)
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.
![Page 43: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/43.jpg)
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" });}
![Page 44: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/44.jpg)
Functional testing
• Test larger piece of your app, or the application as a whole.
• Simulate user interaction, click, type etc.
• Navigate between pages
![Page 45: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/45.jpg)
Functional testing tools
• Selenium• Funcunit• JsTestDriver• Siesta• Watir• DOH Robot (Dojo)• Sahi• Squish (Frog Logic)
![Page 46: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/46.jpg)
Interacting with the DOM
Two main approaches of faking a user
• Synthetic events
• Native events (via Java Applet)
![Page 47: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/47.jpg)
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 differencesDOM Events, Key events, key codes (http://unixpapa.com)
![Page 48: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/48.jpg)
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.
![Page 49: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/49.jpg)
”Browser Drivers”
Opens real browser instances and ’drives’ them
Outputs commands and evaluates result
Can be quite slow
![Page 50: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/50.jpg)
”Browser Drivers”
SeleniumThe most widely used functional testing tool. Firefox
Recorder.
JsTestDriverBy Google. ”Remote JavaScript Console”. IntelliJ and
Eclipse
WatirWeb Application Testing in Ruby. Also a .NET port,
WatiN.
Sahi By TytoSoftware. Has X-browser recorder.
![Page 51: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/51.jpg)
Headless browsers
• “A web browser without a graphical user interface”
• Command line interface
• Great for automating tests, integrating with CI tools (Jenkins, Cruise Control…)
![Page 52: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/52.jpg)
Headless browsers
+ Run tests on command line+ Faster+ Automation+ Doesn’t require an actual browser
- Not 100% accurate, but close.
![Page 53: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/53.jpg)
Headless browsers
PhantomJS (headless WebKit + JavaScript API)
env.js (Runs on Rhino)
JsDom (CommonJS implementation of the DOM)
![Page 54: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/54.jpg)
Phantom JS
Created by Ariya Hidayat (Sencha Inc.)
Fast headless testing
Site scraping
SVG rendering
Supports CoffeeScript
![Page 55: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/55.jpg)
JS Code Coverage
• JsCoverageSeems abandoned
• ScriptCoverGoogle Chrome Plugin
• JsTestDriverAdd-in module for coverage
• JesCov Rhino, Jasmine
![Page 56: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/56.jpg)
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.
![Page 57: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/57.jpg)
CI Tools
• Jenkins
• Cruise Control
• Test Swarm
![Page 58: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/58.jpg)
So which tools are right for me?
![Page 59: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/59.jpg)
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
![Page 60: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/60.jpg)
Resources
http://www.adequatelygood.com/2010/7/Writing-Testable-JavaScript
http://blog.jcoglan.com/2011/07/14/refactoring-towards-testable-javascript-part-1/
![Page 61: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/61.jpg)
Resources - Yahoohttp://screen.yahoo.com/
![Page 62: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/62.jpg)
Resources - GTAC
![Page 63: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/63.jpg)
Finally: wise words
”Without unit tests, you’re not refactoring. You’re just changing shit.”
Hamlet D’Arcy
![Page 64: Java script unit testing](https://reader035.vdocument.in/reader035/viewer/2022081421/554f9feab4c9057b298b4848/html5/thumbnails/64.jpg)
That’s all folks!
Questions?
2012 Mats Bryntse@bryntum