111
Test-Driven JavaScript Eliminating fear and chance from front-end web development

Test-Driven JavaScript Development (JavaZone 2010)

Embed Size (px)

DESCRIPTION

My slides from JavaZone 2010. Watch video:

Citation preview

Page 1: Test-Driven JavaScript Development (JavaZone 2010)

Test-Driven JavaScript

Eliminating fear and chance from front-end web

development

Page 2: Test-Driven JavaScript Development (JavaZone 2010)

Christian Johansen

http://cjohansen.no/http://github.com/cjohansenhttp://gitorious.org/~cjohansenhttp://twitter.com/cjno

Page 3: Test-Driven JavaScript Development (JavaZone 2010)

My book

http://tddjs.com/

Page 4: Test-Driven JavaScript Development (JavaZone 2010)

What we're doing today

•How to unit test JavaScript?

•JavaScript testing challenges

•Tool chain integration

Page 5: Test-Driven JavaScript Development (JavaZone 2010)

How to unit test JavaScript?

Page 6: Test-Driven JavaScript Development (JavaZone 2010)

In-browser test frameworks

Page 7: Test-Driven JavaScript Development (JavaZone 2010)

YUI Test•Part of the YUI framework•Can test any code, regardless of framework•In-browser runner•Built-in mocks•Can ship results over the internet•Supports many output formats (JUnit XML, TAP, JSON ++)

http://developer.yahoo.com/yui/3/test/

Page 8: Test-Driven JavaScript Development (JavaZone 2010)

YUI Test case anatomy

Page 9: Test-Driven JavaScript Development (JavaZone 2010)
Page 10: Test-Driven JavaScript Development (JavaZone 2010)

YUI Test scaffolding

Page 11: Test-Driven JavaScript Development (JavaZone 2010)

YUI Test run

Page 12: Test-Driven JavaScript Development (JavaZone 2010)

YUI Test: The Good

•Easy to get started

•Run in any browser

•Built-in mocks

•Drop into app for integration testing

Page 13: Test-Driven JavaScript Development (JavaZone 2010)

YUI Test: The bad

•Boilerplate HTML fixture

•Manually test all browsers

Page 14: Test-Driven JavaScript Development (JavaZone 2010)

Problem: Impractical workflow

Page 15: Test-Driven JavaScript Development (JavaZone 2010)

Headless runners

Page 16: Test-Driven JavaScript Development (JavaZone 2010)

JSpec•BDD framework

•Runs in browser, Rhino and Node.js

•Emulate DOM with env.js

•Browser-based: Similar to YUI Test

Page 17: Test-Driven JavaScript Development (JavaZone 2010)
Page 18: Test-Driven JavaScript Development (JavaZone 2010)

JSpec Rhino scaffolding

Page 19: Test-Driven JavaScript Development (JavaZone 2010)

JSpec Rhino run

Page 20: Test-Driven JavaScript Development (JavaZone 2010)

JSpec + Rhino: The good

•No browsers

•Fast

Page 21: Test-Driven JavaScript Development (JavaZone 2010)

Problem: It's all fake

Page 22: Test-Driven JavaScript Development (JavaZone 2010)

Just another runtimeNot like any browsers actually in use

Rhino

Page 23: Test-Driven JavaScript Development (JavaZone 2010)

env.js

Just another DOM implementationNot like any DOM implementation in actual use

Page 24: Test-Driven JavaScript Development (JavaZone 2010)
Page 25: Test-Driven JavaScript Development (JavaZone 2010)
Page 26: Test-Driven JavaScript Development (JavaZone 2010)
Page 27: Test-Driven JavaScript Development (JavaZone 2010)
Page 28: Test-Driven JavaScript Development (JavaZone 2010)
Page 29: Test-Driven JavaScript Development (JavaZone 2010)
Page 30: Test-Driven JavaScript Development (JavaZone 2010)
Page 31: Test-Driven JavaScript Development (JavaZone 2010)
Page 32: Test-Driven JavaScript Development (JavaZone 2010)
Page 33: Test-Driven JavaScript Development (JavaZone 2010)

I hear these are popular

Page 34: Test-Driven JavaScript Development (JavaZone 2010)

...and these

Page 35: Test-Driven JavaScript Development (JavaZone 2010)

Manual testing is time consuming

Page 36: Test-Driven JavaScript Development (JavaZone 2010)

The best from both worlds

Page 37: Test-Driven JavaScript Development (JavaZone 2010)

JsTestDriver

Page 38: Test-Driven JavaScript Development (JavaZone 2010)

JsTestDriver.conf

Page 39: Test-Driven JavaScript Development (JavaZone 2010)
Page 40: Test-Driven JavaScript Development (JavaZone 2010)

Start JsTestDriver Server

java -jar JsTestDriver-1.2.2.jar --port 4224

Page 41: Test-Driven JavaScript Development (JavaZone 2010)

Capture Target Browsers

Page 42: Test-Driven JavaScript Development (JavaZone 2010)
Page 43: Test-Driven JavaScript Development (JavaZone 2010)
Page 44: Test-Driven JavaScript Development (JavaZone 2010)
Page 45: Test-Driven JavaScript Development (JavaZone 2010)
Page 46: Test-Driven JavaScript Development (JavaZone 2010)
Page 47: Test-Driven JavaScript Development (JavaZone 2010)

JsTestDriver Run

Page 48: Test-Driven JavaScript Development (JavaZone 2010)

Bonus features•Alternative assertion frameworks

•Supports QUnit, YUI, Jasmine

•JUnit XML Output

•Coverage plugin

Page 49: Test-Driven JavaScript Development (JavaZone 2010)

CLI Helper

$ gem install jstdutil$ export JSTESTDRIVER_HOME=~/bin/jstestdriver

Page 50: Test-Driven JavaScript Development (JavaZone 2010)

Pretty colors

Page 51: Test-Driven JavaScript Development (JavaZone 2010)

With errors

Page 52: Test-Driven JavaScript Development (JavaZone 2010)

Also...

$ jsautotest

Runs affected tests on each save

Page 53: Test-Driven JavaScript Development (JavaZone 2010)

Eclipse

Page 54: Test-Driven JavaScript Development (JavaZone 2010)

Eclipse

Page 55: Test-Driven JavaScript Development (JavaZone 2010)

Eclipse run

Page 56: Test-Driven JavaScript Development (JavaZone 2010)

IntelliJ IDEA plugin also available

Page 57: Test-Driven JavaScript Development (JavaZone 2010)

Just released

Page 58: Test-Driven JavaScript Development (JavaZone 2010)

JavaScript testing challenges

Page 59: Test-Driven JavaScript Development (JavaZone 2010)

XMLHttpRequest

•Needs a server responding

•Makes tests run slow(er)

•Unsuitable for unit tests

Page 60: Test-Driven JavaScript Development (JavaZone 2010)

Solution: Encapsulate

•Simple and elegant

•Looser coupling

•Easy to test

Page 61: Test-Driven JavaScript Development (JavaZone 2010)

Example: Chat client

Page 62: Test-Driven JavaScript Development (JavaZone 2010)

Anatomy

Page 63: Test-Driven JavaScript Development (JavaZone 2010)

messageFormController

this.view (form)this.model (cometClient)

onSubmit

messageListController

this.view (dl)this.model (cometClient)

cometClient

Page 64: Test-Driven JavaScript Development (JavaZone 2010)

What's the trick?

•All network access goes through cometClient

•observable supports same API as cometClient

•Use observable in tests

Page 65: Test-Driven JavaScript Development (JavaZone 2010)

What about cometClient?

We'll get there

Page 66: Test-Driven JavaScript Development (JavaZone 2010)

Event Handlers

•Touch, keyboard, mouse events

•Cross-browser issues

•Cumbersome to manually fire

Page 67: Test-Driven JavaScript Development (JavaZone 2010)

messageFormController

this.view (form)this.model (cometClient)

onSubmit

messageListController

this.view (dl)this.model (cometClient)

cometClient

Page 68: Test-Driven JavaScript Development (JavaZone 2010)

Submitting message

Page 69: Test-Driven JavaScript Development (JavaZone 2010)

Solution: Decouple code

•Simple

•Testable

•Often makes sense API-wise

Page 70: Test-Driven JavaScript Development (JavaZone 2010)
Page 71: Test-Driven JavaScript Development (JavaZone 2010)

Testing event handlers

•Verify that setView adds event handler to form element for submit event

•Verify that the handler is postMessage, bound to the controller

•Test postMessage separately

Page 72: Test-Driven JavaScript Development (JavaZone 2010)

Stubs and Mocks

Page 73: Test-Driven JavaScript Development (JavaZone 2010)

Disclaimer: I wrote thathttp://cjohansen.no/sinon/

Page 74: Test-Driven JavaScript Development (JavaZone 2010)

Sinon.JS Spies

•Wraps functions

•Does not interrupt normal execution

•Logs all calls and related data

Page 75: Test-Driven JavaScript Development (JavaZone 2010)

Using Sinon.JS spies

Page 76: Test-Driven JavaScript Development (JavaZone 2010)

sinon.testCase()

•Automatically verifies mocks

•Automatically restores all fakes

•Provides useful utilities (more later)

Page 77: Test-Driven JavaScript Development (JavaZone 2010)

Verify that an event handler was added

Page 78: Test-Driven JavaScript Development (JavaZone 2010)

Testing the handler

Page 79: Test-Driven JavaScript Development (JavaZone 2010)
Page 80: Test-Driven JavaScript Development (JavaZone 2010)

Testing event handlers

•Verify that setView adds event handler to form element for submit event

•Verify that the handler is postMessage, bound to the controller

•Test postMessage separately

Page 81: Test-Driven JavaScript Development (JavaZone 2010)
Page 82: Test-Driven JavaScript Development (JavaZone 2010)

Use an ad hoc stub

Page 83: Test-Driven JavaScript Development (JavaZone 2010)

Integration: Simulate

Page 84: Test-Driven JavaScript Development (JavaZone 2010)

Testing actual network access

Using Sinon.JS

Page 85: Test-Driven JavaScript Development (JavaZone 2010)

Configure a fake server

Page 86: Test-Driven JavaScript Development (JavaZone 2010)

Fake JSON response{ "message": [{ "id": 1, "user": "Johansen", "message": "oh hai" }],

"token": "1"}

The cometClient format, an array of one new message

Page 87: Test-Driven JavaScript Development (JavaZone 2010)

Force fake server to respond

Page 88: Test-Driven JavaScript Development (JavaZone 2010)

What happened?

•GET /chat?1283370174112

•Fake server recognizes /\/chat\?\d+/

•this.server.respond(); fakes a response

•cometClient dispatches canned data

Page 89: Test-Driven JavaScript Development (JavaZone 2010)

Testing timers

•setTimeout/setInterval

•Causes slow(er) tests

•Causes asynchronous tests

Page 90: Test-Driven JavaScript Development (JavaZone 2010)

Solution: Fake it

Page 91: Test-Driven JavaScript Development (JavaZone 2010)

Toolchain

Page 92: Test-Driven JavaScript Development (JavaZone 2010)
Page 93: Test-Driven JavaScript Development (JavaZone 2010)

JsTestDriver and Maven

http://code.google.com/p/jsd-maven/

Page 94: Test-Driven JavaScript Development (JavaZone 2010)

XML Pushups

Page 95: Test-Driven JavaScript Development (JavaZone 2010)
Page 96: Test-Driven JavaScript Development (JavaZone 2010)

Can you take one more?

Page 97: Test-Driven JavaScript Development (JavaZone 2010)
Page 98: Test-Driven JavaScript Development (JavaZone 2010)

Continuous Integration

Page 99: Test-Driven JavaScript Development (JavaZone 2010)

Hudson setup

•"Free-style software project"

•Hudson xUnit Plugin

Page 100: Test-Driven JavaScript Development (JavaZone 2010)
Page 101: Test-Driven JavaScript Development (JavaZone 2010)
Page 102: Test-Driven JavaScript Development (JavaZone 2010)

java -jar test/JsTestDriver-1.2.2.jar \ --config jsTestDriver.conf \ --reset \ --server http://localhost:4223 \ --tests all \ --testOutput .

Page 103: Test-Driven JavaScript Development (JavaZone 2010)

Project overview

Page 104: Test-Driven JavaScript Development (JavaZone 2010)

Test case

Page 105: Test-Driven JavaScript Development (JavaZone 2010)

Failed test (IE6)

Page 106: Test-Driven JavaScript Development (JavaZone 2010)

Risky time: Live demo•Add a feature - test first

•Autotest

•Test with Maven

•CI with Hudson

•Test in multiple browsers

Page 107: Test-Driven JavaScript Development (JavaZone 2010)

Feature: @-messages

Highlight messages directed at current user

Page 108: Test-Driven JavaScript Development (JavaZone 2010)

messageFormController

this.view (form)this.model (cometClient)

onSubmit

messageListController

this.view (dl)this.model (cometClient)

cometClient

Page 109: Test-Driven JavaScript Development (JavaZone 2010)

Questions?

Page 110: Test-Driven JavaScript Development (JavaZone 2010)

My book

http://tddjs.com/

Page 111: Test-Driven JavaScript Development (JavaZone 2010)

Thanks for your time!•http://cjohansen.no/

•http://github.com/cjohansen/

•http://gitorious.org/~cjohansen/

•http://twitter.com/cjno/

[email protected]