John Resig on JavaScript testing, performance analysis, and jQuery 1.4
John Resig, of jQuery and other fame, spoke tonight at the BayJax meetup in the Yahoo! cafeteria. His slides are probably online somewhere, but they are lucid, informative, illustrated with pictures and code samples, and written by someone who knows what he’s talking about, not to mention who was paying attention while writing them. (Update: Video on iTunes and not on iTunes.) If that’s not your bag, you’ll want to read my notes instead:
PART I: Testing JavaScript
javascript testing is different from desktop/server testing
- cross-browser issues
there are a lot of javascript testing frameworks!
- long tail
- it’s easy to write one
basic components for a testing framework
- the usual, plus async tests
- minimum: assertions
(’glorified assertion-and-logging framework’)
- async tests
- pause (stop executing other tests) and resume
why write your own?
- a good way to understand what testing is for
- not too many cross-browser issues
popular frameworks:
- (none)
- JSUnit
- 2001, and looks it
- YUITest
- good code, supports async tests and event simulation
- (looks like nested contexts?)
- QUnit
- async testing, test timeouts
- no dependencies
- easy to use
- FireUnit
- firebug extension
standardization
- CommonJS: standard API across client and server environments
- including testing API, now adopted by QUnit (I think)
server-side testing of client-side code
- usually Java + Rhino
- Crosscheck (Java)
- Env.js (pure JS)
- BlueRidge (Env.js + Screw.unit + Rhino)
browser launching
- WebDriver (Java)
- Watir (Ruby)
- JsTestDriver (Java)
- Selenium RC (Java)
distributed (for scale)
- Selenium Grid - on Amazon servers
- TestSwarm - crowd-sourced
PART II: Accurately Measuring JavaScript
major use cases:
- same code, different platforms
- which browser is fastest?
- different code, same platform
- which framework is fastest?
- how should we implement this?
same code, different platform
- SunSpider (WebKit), V8 (Chrome), Dromaeo (Mozilla)
… statistics…
error rate
- faster tests => less accuracy
- faster *browsers* => less accuracy
- dromaeo/v8 test runs/sec instead of msec/run
- use harmonic mean to average
different code, same platform
- most solutions are bad
- few runs, inaccurate
- garbage collection
- use mode instead of mean
- less accurate than mean, but more consistent
- don’t discard “bad” results - GC is significant
- may reflect memory issues
- getTime() “very very imprecise”
- 15ms intervals on XP (except FF/Chrome)
- IE in Wine gives you precision, but it’s not IE on Windows
- browser tools
- Safari, Firebug, IE 8 profilers
- DynaTrace Ajax for IE 6-8
- Shark - watches internal function calls
PART III: jQuery 1.4
- complexity reduction
- bubbling change, submit, focus, blur
- required script loading
analyzing performance
- stop measuring absolute execution time
- improve code quality and flow
complexity analysis
- count function calls instead of seconds
- may indicate not slowness, but poorly written code
- remove() did a lot more work than it needed to
- and so did everything that used remove()
event bubbling in IE
- focus, blur, change, and submit don’t bubble
- alternative solutions: piggyback on events that DO bubble
- focus/blur: use focusin/focusout
- submit: watch for click… or ‘enter’ keypress…
- change: basically reimplement the whole event
- track previous value
- watch for keyup navigation, checkbox clicks
- beforeactive on radio buttons
jQuery.require()
- don’t try to load a script multiple times
- load synchronously if needed for dependent code
- load asynchronously if you can get away with it!
URL mapping
- require(’ajax’) => ajax.js
- namespaces expand to URLs
PART IV: HTML 5 Elements in IE
problem #1
- unknown elements are unstyled, and “inner contents escape”
- fix: document.createElement(’section’) makes section work
- html5shiv does that for all HTML5
problem #2
- unknown elements can’t hold other unknown elements
- even with html5shiv
- no fix
problem #3
- nodeName of unknown elements is treated as XML
- fix: don’t assume nodeName is uppercase
problem #4
- injecting unknown elements via innerHTML fails
- “fix”: parse HTML and build DOM in JS
Q&A:
… i zoned out…
Q: clojure?
A: framework… okay. compiler… pretty slick!
- but designed to compile your whole application
- can’t compile the framework separately