Writing and Testing JavaScript-heavy Web 2.0 apps with JSUnit <ul><li>Authors: </li></ul><ul><ul><li>Alex Chaffee, Pivotal...
Abstract With the advent of the so-called Web 2.0 platform, more and more applications are using client-side JavaScript fo...
JS Application Architectures <ul><li>Traditional: Minimal JS </li></ul><ul><ul><li>JS for validation </li></ul></ul><ul><u...
JS Application Architectures (cont.) <ul><li>AJAX Architecture </li></ul><ul><ul><li>Widgets and functions live on client ...
JS Application Architectures (cont.) <ul><li>Dynamic Architecture:  server-generated JS </li></ul><ul><ul><li>RJS </li></u...
Application Architectures (cont.) <ul><li>Client-Server </li></ul><ul><li>JS MVC: Heavy JS </li></ul><ul><ul><li>In this a...
Application Architectures (cont.) <ul><li>Hybrid </li></ul><ul><ul><li>Naturally, you can mix and match the above techniqu...
Testing Strategies <ul><li>Unit Testing: </li></ul><ul><ul><li>JSUnit </li></ul></ul><ul><li>Integration Testing: </li></u...
JavaScript Essence <ul><li>Dynamic </li></ul><ul><li>Interpreted </li></ul><ul><li>Prototype-based OO </li></ul><ul><li>Ob...
JavaScript Cons <ul><li>Functions have loose binding </li></ul><ul><ul><li>“ this” isn't always correct </li></ul></ul><ul...
JavaScript Tools and Libraries
Firefox Extensions <ul><li>Web Developer </li></ul><ul><li>Firebug ROCKS </li></ul>
Development Environments <ul><li>IDEA </li></ul><ul><li>Eclipse </li></ul><ul><li>TextMate </li></ul><ul><li>? </li></ul>
prototype.js Library <ul><li>bind </li></ul><ul><li>$ </li></ul><ul><li>$H, $A, each, etc. </li></ul><ul><li>extend </li><...
JS UI libraries <ul><li>script.aculo.us </li></ul><ul><ul><li>Very Good </li></ul></ul><ul><ul><li>Popular (easy to find h...
Asset Packager <ul><li>Combines multiple JS files into one </li></ul><ul><ul><li>Also CSS </li></ul></ul><ul><li>Reduces L...
JSUnit <ul><li>“ Controlling The Insanity” </li></ul><ul><li>Unit Testing is essential for all but the most trivial JavaSc...
Pivotal Assertions
clock.js <ul><li>Testing utility class we wrote </li></ul><ul><li>Overrides setTimeout </li></ul><ul><li>Allows unit testi...
ajax.js <ul><li>AjaxUnit </li></ul><ul><li>Overrides Prototype AJAX classes </li></ul><ul><li>Stubs out the network interf...
Mock Objects in JS <ul><li>We don’t know of any real mocking framework for JS </li></ul><ul><li>We use stubs, spies, objec...
Client-Server Communication
Client-Server Communication: Let me count the ways <ul><li>HTTP </li></ul><ul><ul><li>Including GET, POST, cookies, etc. <...
AJAX <ul><li>“ Asynchronous JavaScript And XML” </li></ul><ul><li>Client calls server with CGI GET or POST via XMLHttpRequ...
AJAX+XML <ul><li>Response contains XML </li></ul><ul><li>Original implementation of AJAX </li></ul><ul><li>Not used much n...
JSON <ul><li>Evaluates to JS values (hashes and arrays) </li></ul><ul><li>Example: </li></ul><ul><ul><li>{   &quot;Image&q...
AJAX+JSON (AJAJ?) <ul><li>Proper client-server communication </li></ul><ul><li>Client sends requests in CGI, gets response...
AJAX+HTML <ul><li>Server executes RHTML/JSP/etc. </li></ul><ul><li>AJAX response contains HTML </li></ul><ul><li>Client sp...
AJAX+JS <ul><li>AJAX response contains JavaScript code </li></ul><ul><li>Client calls  eval()  on it </li></ul><ul><li>Pow...
RJS <ul><li>Part of Ruby on Rails </li></ul><ul><li>Generates JS via Ruby methods </li></ul><ul><li>Not as scary as raw JS...
Latency: The AJAX killer <ul><li>This AJAX stuff really is client-server communication </li></ul><ul><li>If the server is ...
Solving Latency <ul><li>The Easy Way:  </li></ul><ul><ul><li>Use a spinny icon </li></ul></ul><ul><ul><li>Still requires U...
Solving Latency <ul><li>The Hard Way: </li></ul><ul><ul><li>To solve, you must write a lot of code on the client to react ...
JS MVC Architecture JSON Model Objects Notify View Components Render DOM User Events Enqueue Command Objects Execute / und...
Integration Testing with Selenium <ul><li>Selenium… </li></ul><ul><ul><li>Runs in the browser </li></ul></ul><ul><ul><li>E...
Q&A
More Examples
Clock <ul><li>We wrote our JS “Mock Clock” test-first </li></ul><ul><ul><li>Actually, it’s a stub, not a mock :-) </li></u...
Weaver <ul><li>The Weaver takes two arrays and returns the set of changes required to transform one into the other </li></...
DateWidget <ul><li>We wrapped Yahoo’s YUI Calendar widget to add a text field with validation and pop-up-on-activate </li>...
Server Proxy <ul><li>Illustrates AjaxUnit (ajax.js) mocking out the networking layer </li></ul>
Add Note Command <ul><li>Tests the command which adds a note (comment) to a story </li></ul><ul><ul><li>Does not test the ...
Login Widget <ul><li>PeerToPatent uses page caching, so we have to render the “you’re logged in / please log in” area of t...
Cacheable Flash <ul><li>Not that kind of Flash… “Flash” is Rails for “Message Box” </li></ul><ul><li>In order for dynamic ...
Cookie Library <ul><li>Illustrates testing a third-party library </li></ul><ul><li>We found bugs in it, esp. IE 7 </li></u...
JS Paginator <ul><li>Illustrates receiving JSON with data </li></ul><ul><li>Download (actually render) entire data set on ...
Experimentation <ul><li>Since this is an agile conference, if there's time and interest, we can get volunteers from the au...
Where to find more info? <ul><li>http://jsunit.net </li></ul><ul><li>http://pivotallabs.com </li></ul>
Upcoming SlideShare
Loading in...5
×

Writing and Testing JavaScript-heavy Web 2.0 apps with JSUnit

10,900

Published on

With the advent of the so-called Web 2.0 platform, more and more applications are using client-side JavaScript for vital features. In fact, some applications are so JS-heavy that they redefine JavaScript as a full-fledged application development language. In this tutorial we discuss some architectural considerations of JS- and AJAX-heavy applications and present in detail our testing framework, with plenty of code examples.

Published in: Business, Technology
3 Comments
8 Likes
Statistics
Notes
No Downloads
Views
Total Views
10,900
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
293
Comments
3
Likes
8
Embeds 0
No embeds

No notes for slide

Writing and Testing JavaScript-heavy Web 2.0 apps with JSUnit

  1. 1. Writing and Testing JavaScript-heavy Web 2.0 apps with JSUnit <ul><li>Authors: </li></ul><ul><ul><li>Alex Chaffee, Pivotal Labs </li></ul></ul><ul><ul><li>Edward Hieatt, Pivotal Labs </li></ul></ul>
  2. 2. Abstract With the advent of the so-called Web 2.0 platform, more and more applications are using client-side JavaScript for vital features. In fact, some applications are so JS-heavy that they redefine JavaScript as a full-fledged application development language. In this tutorial we discuss some architectural considerations of JS- and AJAX-heavy applications and present in detail our testing framework, with plenty of code examples and live demos.
  3. 3. JS Application Architectures <ul><li>Traditional: Minimal JS </li></ul><ul><ul><li>JS for validation </li></ul></ul><ul><ul><li>JS for user responsiveness </li></ul></ul><ul><ul><li>JS for DHTML </li></ul></ul><ul><ul><li>JS for layout tweaks (where CSS falls down) </li></ul></ul>
  4. 4. JS Application Architectures (cont.) <ul><li>AJAX Architecture </li></ul><ul><ul><li>Widgets and functions live on client </li></ul></ul><ul><ul><li>Use XMLHttpRequest for immediate or background requests to server </li></ul></ul><ul><ul><li>Use JSON or XML for data transport </li></ul></ul>
  5. 5. JS Application Architectures (cont.) <ul><li>Dynamic Architecture: server-generated JS </li></ul><ul><ul><li>RJS </li></ul></ul><ul><ul><li>Google Web Toolkit </li></ul></ul><ul><ul><li>Big advantage: </li></ul></ul><ul><ul><ul><li>unified codebase -> DRY </li></ul></ul></ul><ul><ul><li>Disadvantages: </li></ul></ul><ul><ul><ul><li>Latency </li></ul></ul></ul><ul><ul><ul><li>Harder to test </li></ul></ul></ul>
  6. 6. Application Architectures (cont.) <ul><li>Client-Server </li></ul><ul><li>JS MVC: Heavy JS </li></ul><ul><ul><li>In this architecture, the JavaScript code takes the form of a full-fledged application. Using JSON to transfer data back and forth between the server-side API, the JavaScript application maintains its own domain objects and executes its own business rules. </li></ul></ul><ul><ul><li>Can violate DRY </li></ul></ul>
  7. 7. Application Architectures (cont.) <ul><li>Hybrid </li></ul><ul><ul><li>Naturally, you can mix and match the above techniques </li></ul></ul><ul><ul><li>Complicates your coding and testing </li></ul></ul><ul><ul><li>Can violate DRY </li></ul></ul>
  8. 8. Testing Strategies <ul><li>Unit Testing: </li></ul><ul><ul><li>JSUnit </li></ul></ul><ul><li>Integration Testing: </li></ul><ul><ul><li>Selenium </li></ul></ul><ul><ul><li>WATIR </li></ul></ul>
  9. 9. JavaScript Essence <ul><li>Dynamic </li></ul><ul><li>Interpreted </li></ul><ul><li>Prototype-based OO </li></ul><ul><li>Object = Hash </li></ul><ul><ul><li>Everything (even Function) is a Hash </li></ul></ul><ul><li>Sort of a mutant hybrid of Java and Ruby </li></ul>
  10. 10. JavaScript Cons <ul><li>Functions have loose binding </li></ul><ul><ul><li>“ this” isn't always correct </li></ul></ul><ul><ul><li>Workaround: Use bind (part of prototype.js) </li></ul></ul><ul><li>Frustrating syntax and semantics </li></ul><ul><li>Symbols are globally scoped by default </li></ul><ul><ul><li>You must remember “this” </li></ul></ul><ul><ul><li>Too easy to make global variables </li></ul></ul><ul><li>null vs. undefined vs. 0 </li></ul><ul><li>All members are public </li></ul><ul><li>No OO inheritance </li></ul><ul><ul><li>Several hacks to simulate inheritance </li></ul></ul><ul><ul><li>Rely more on composition </li></ul></ul><ul><li>Browser differences (esp. DOM API) and bugs </li></ul><ul><li>No “include” or “require” </li></ul><ul><ul><li>We rolled our own </li></ul></ul><ul><li>Painful debugging </li></ul><ul><li>Unreliable stack traces </li></ul><ul><li>Two different GCs </li></ul><ul><ul><li>Memory leaks via DOM </li></ul></ul><ul><li>Third-party libraries rarely tested </li></ul>
  11. 11. JavaScript Tools and Libraries
  12. 12. Firefox Extensions <ul><li>Web Developer </li></ul><ul><li>Firebug ROCKS </li></ul>
  13. 13. Development Environments <ul><li>IDEA </li></ul><ul><li>Eclipse </li></ul><ul><li>TextMate </li></ul><ul><li>? </li></ul>
  14. 14. prototype.js Library <ul><li>bind </li></ul><ul><li>$ </li></ul><ul><li>$H, $A, each, etc. </li></ul><ul><li>extend </li></ul><ul><li>Ajax.Request </li></ul><ul><li>Element.hide </li></ul><ul><li>Other useful stuff </li></ul>
  15. 15. JS UI libraries <ul><li>script.aculo.us </li></ul><ul><ul><li>Very Good </li></ul></ul><ul><ul><li>Popular (easy to find help) </li></ul></ul><ul><li>Yahoo UI </li></ul><ul><ul><li>Excellent </li></ul></ul><ul><ul><li>Drag and drop, animation, calendar, etc. </li></ul></ul>
  16. 16. Asset Packager <ul><li>Combines multiple JS files into one </li></ul><ul><ul><li>Also CSS </li></ul></ul><ul><li>Reduces Latency </li></ul><ul><li>Also Steve Conover’s inline merger looks promising </li></ul>
  17. 17. JSUnit <ul><li>“ Controlling The Insanity” </li></ul><ul><li>Unit Testing is essential for all but the most trivial JavaScript </li></ul>
  18. 18. Pivotal Assertions
  19. 19. clock.js <ul><li>Testing utility class we wrote </li></ul><ul><li>Overrides setTimeout </li></ul><ul><li>Allows unit testing of time-based operations without sleeping </li></ul>
  20. 20. ajax.js <ul><li>AjaxUnit </li></ul><ul><li>Overrides Prototype AJAX classes </li></ul><ul><li>Stubs out the network interface </li></ul><ul><li>Allows unit testing of AJAX calls </li></ul>
  21. 21. Mock Objects in JS <ul><li>We don’t know of any real mocking framework for JS </li></ul><ul><li>We use stubs, spies, object mothers and mock methods </li></ul>
  22. 22. Client-Server Communication
  23. 23. Client-Server Communication: Let me count the ways <ul><li>HTTP </li></ul><ul><ul><li>Including GET, POST, cookies, etc. </li></ul></ul><ul><li>CGI </li></ul><ul><li>AJAX+XML </li></ul><ul><li>AJAX+JSON </li></ul><ul><li>AJAX+HTML </li></ul><ul><li>AJAX+JS </li></ul><ul><li>RJS </li></ul>
  24. 24. AJAX <ul><li>“ Asynchronous JavaScript And XML” </li></ul><ul><li>Client calls server with CGI GET or POST via XMLHttpRequest API </li></ul><ul><li>Server responds </li></ul><ul><li>Client does something without redrawing entire page </li></ul>
  25. 25. AJAX+XML <ul><li>Response contains XML </li></ul><ul><li>Original implementation of AJAX </li></ul><ul><li>Not used much now (?) </li></ul><ul><li>I've heard of doing XSL but that's mostly on IE-only apps </li></ul>
  26. 26. JSON <ul><li>Evaluates to JS values (hashes and arrays) </li></ul><ul><li>Example: </li></ul><ul><ul><li>{ &quot;Image&quot;: { &quot;Width&quot;: 800, &quot;Height&quot;: 600, &quot;Title&quot;: &quot;View from 15th Floor&quot;, &quot;Thumbnail&quot;: { &quot;Url&quot;: &quot;http: //scd.mmb1.com/image/481989943&quot;, &quot;Height&quot;: 125, &quot;Width&quot;: &quot;100&quot; }, &quot;IDs&quot;: [116, 943, 234, 38793] } } </li></ul></ul>
  27. 27. AJAX+JSON (AJAJ?) <ul><li>Proper client-server communication </li></ul><ul><li>Client sends requests in CGI, gets responses as pure data </li></ul><ul><li>Client evaluates data, actively performs response </li></ul><ul><li>Interacts with DOM </li></ul><ul><li>Creates/removes/modifies/copies HTML elements </li></ul>
  28. 28. AJAX+HTML <ul><li>Server executes RHTML/JSP/etc. </li></ul><ul><li>AJAX response contains HTML </li></ul><ul><li>Client splats it onto the page </li></ul>
  29. 29. AJAX+JS <ul><li>AJAX response contains JavaScript code </li></ul><ul><li>Client calls eval() on it </li></ul><ul><li>Powerful and a little scary </li></ul><ul><li>Hard to test </li></ul>
  30. 30. RJS <ul><li>Part of Ruby on Rails </li></ul><ul><li>Generates JS via Ruby methods </li></ul><ul><li>Not as scary as raw JS since it’s coming from a tested library </li></ul>
  31. 31. Latency: The AJAX killer <ul><li>This AJAX stuff really is client-server communication </li></ul><ul><li>If the server is slow, your app crawls to a halt -- and inside a page, not just between pages </li></ul><ul><li>Less user feedback for a hung AJAX call </li></ul><ul><ul><li>Can lead to multiple clicks, reloads, confusion, etc. </li></ul></ul>
  32. 32. Solving Latency <ul><li>The Easy Way: </li></ul><ul><ul><li>Use a spinny icon </li></ul></ul><ul><ul><li>Still requires UI/UE design </li></ul></ul>
  33. 33. Solving Latency <ul><li>The Hard Way: </li></ul><ul><ul><li>To solve, you must write a lot of code on the client to react immediately to user actions, then queue up requests and deal gracefully once the server reponds </li></ul></ul><ul><ul><li>Error handling </li></ul></ul><ul><ul><li>Command queue </li></ul></ul><ul><ul><li>Undo </li></ul></ul><ul><ul><li>Dynamic/incremental data updates </li></ul></ul><ul><ul><li>This leads naturally to true MVC in JS </li></ul></ul>
  34. 34. JS MVC Architecture JSON Model Objects Notify View Components Render DOM User Events Enqueue Command Objects Execute / undo AJAX (CGI)
  35. 35. Integration Testing with Selenium <ul><li>Selenium… </li></ul><ul><ul><li>Runs in the browser </li></ul></ul><ul><ul><li>Executes your app in a frame </li></ul></ul><ul><ul><li>Simulates user actions via JavaScript </li></ul></ul><ul><ul><li>Goes all the way to the server and back </li></ul></ul><ul><li>Complementary to JSUnit </li></ul><ul><ul><li>JSUnit tests JS pages and libraries only, not interaction with server </li></ul></ul><ul><li>Selenium is fun to watch </li></ul><ul><li>Integrated into Continuous Integration like JSUnit </li></ul><ul><li>Catch our talks on Wednesday (Selenium) and Thursday (CI) </li></ul>
  36. 36. Q&A
  37. 37. More Examples
  38. 38. Clock <ul><li>We wrote our JS “Mock Clock” test-first </li></ul><ul><ul><li>Actually, it’s a stub, not a mock :-) </li></ul></ul><ul><li>Illustrates a true (isolated) unit test of a utility class </li></ul>
  39. 39. Weaver <ul><li>The Weaver takes two arrays and returns the set of changes required to transform one into the other </li></ul><ul><li>Used by Tracker’s list widgets </li></ul><ul><li>Illustrates use of roll-your-own test spies </li></ul>
  40. 40. DateWidget <ul><li>We wrapped Yahoo’s YUI Calendar widget to add a text field with validation and pop-up-on-activate </li></ul><ul><li>Illustrates </li></ul><ul><ul><li>Testing with UI events </li></ul></ul><ul><ul><li>Using a “demo.html” page </li></ul></ul><ul><ul><li>Wrapping a third-party widget with tests </li></ul></ul>
  41. 41. Server Proxy <ul><li>Illustrates AjaxUnit (ajax.js) mocking out the networking layer </li></ul>
  42. 42. Add Note Command <ul><li>Tests the command which adds a note (comment) to a story </li></ul><ul><ul><li>Does not test the networking layer, just the command object </li></ul></ul><ul><li>Demonstrates use of stubs and object mother (JsonFactory) </li></ul>
  43. 43. Login Widget <ul><li>PeerToPatent uses page caching, so we have to render the “you’re logged in / please log in” area of the screen in JavaScript </li></ul>
  44. 44. Cacheable Flash <ul><li>Not that kind of Flash… “Flash” is Rails for “Message Box” </li></ul><ul><li>In order for dynamic information to be rendered inside of a statically cached page, we put it into a cookie, and render the cookie’s contents with JavaScript </li></ul>
  45. 45. Cookie Library <ul><li>Illustrates testing a third-party library </li></ul><ul><li>We found bugs in it, esp. IE 7 </li></ul><ul><ul><li>We had to patch it </li></ul></ul>
  46. 46. JS Paginator <ul><li>Illustrates receiving JSON with data </li></ul><ul><li>Download (actually render) entire data set on page load, then render some at a time </li></ul><ul><ul><li>Doesn’t scale to large datasets, like Rico LiveGrid does </li></ul></ul>
  47. 47. Experimentation <ul><li>Since this is an agile conference, if there's time and interest, we can get volunteers from the audience to come up and pair program with the presenters on stage. solving problems posed by the audience. </li></ul>
  48. 48. Where to find more info? <ul><li>http://jsunit.net </li></ul><ul><li>http://pivotallabs.com </li></ul>
  1. A particular slide catching your eye?

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

×