Java script unit testing

64
JavaScript Unit Testing 2012 Mats Bryntse @bryntum

description

My talk at Community Day in Stockholm.

Transcript of Java script unit testing

Page 1: Java script unit testing

JavaScript Unit Testing

2012 Mats Bryntse@bryntum

Page 2: Java script unit testing

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

What we do

JavaScript scheduling and Gantt charts

Siesta (JS Test Tool)

Page 4: Java script unit testing

</SELFPROMOTION>

Page 5: Java script unit testing

First, a quick survey:

How many of you...

Page 6: Java script unit testing

• 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

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

Reasons for testing JavaScript

Page 9: Java script unit testing

A typical web app...

Interwebs

http://www.app.com

Page 10: Java script unit testing

The backend

• Single controlled platform

• Simple to test and refactor

• Good IDEs and tools

C#Java

PHP

Page 11: Java script unit testing

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

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

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

Reasons for testing JavaScript contd.

Page 15: Java script unit testing

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

Refactoring is painful

Pain of Refactoring0

20

40

60

80

100

120

BackendFrontend

Page 17: Java script unit testing

X-browser testing doesn’t scale

• iOS• Android• IE Mobile• Blackberry• Firefox mobile• ...

Page 18: Java script unit testing

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

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

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

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

Code handover

New guy, scared

Page 23: Java script unit testing

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

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

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

Writing testable JS

Page 27: Java script unit testing

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

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

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

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

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

Tools

Page 33: Java script unit testing

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

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

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

Jasmine

• Simple DOM-less testing

• BDD syntax

• Borrows “the best parts” of ScrewUnit, JSSpec, JSpec, and RSpec.

Page 37: Java script unit testing

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

Jasmine matchers

Page 39: Java script unit testing

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

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

Testing Ajax

Page 42: Java script unit testing

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

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

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

Functional testing tools

• Selenium• Funcunit• JsTestDriver• Siesta• Watir• DOH Robot (Dojo)• Sahi• Squish (Frog Logic)

Page 46: Java script unit testing

Interacting with the DOM

Two main approaches of faking a user

• Synthetic events

• Native events (via Java Applet)

Page 47: Java script unit testing

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

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

”Browser Drivers”

Opens real browser instances and ’drives’ them

Outputs commands and evaluates result

Can be quite slow

Page 50: Java script unit testing

”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

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

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

Headless browsers

PhantomJS (headless WebKit + JavaScript API)

env.js (Runs on Rhino)

JsDom (CommonJS implementation of the DOM)

Page 54: Java script unit testing

Phantom JS

Created by Ariya Hidayat (Sencha Inc.)

Fast headless testing

Site scraping

SVG rendering

Supports CoffeeScript

Page 55: Java script unit testing

JS Code Coverage

• JsCoverageSeems abandoned

• ScriptCoverGoogle Chrome Plugin

• JsTestDriverAdd-in module for coverage

• JesCov Rhino, Jasmine

Page 56: Java script unit testing

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

CI Tools

• Jenkins

• Cruise Control

• Test Swarm

Page 58: Java script unit testing

So which tools are right for me?

Page 59: Java script unit testing

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

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

Resources - Yahoohttp://screen.yahoo.com/

Page 62: Java script unit testing

Resources - GTAC

Page 63: Java script unit testing

Finally: wise words

”Without unit tests, you’re not refactoring. You’re just changing shit.”

Hamlet D’Arcy

Page 64: Java script unit testing

That’s all folks!

Questions?

2012 Mats Bryntse@bryntum