Testing Web Applications, Colin Putney, Whistler
(I enlivened the start of this talk by upsetting a water jug over the chair next to me, which made life interesting for Bill Dargel when he arrived and sat there while I was plugging in my computer and so momentarily distracted from warning him.)
Colin had what some Smalltalkers may have thought of as God's own job, working in the ski resort at Whistler, where they have a 20cm rule; if the snow exceeds 20cm, work does not start before noon. Except that I suspect his rates took account of the job's fringe benefits, it would seem ideal work for a skiing Smalltalker.
He wanted to test the application logic behind the web page. Separating the presentation from the logic began with cgi and developed to putting code inside html. This is not enough for what Colin needs. His framework reads in the template and processes it. It reads the source into a DOM, does XSLT transformations on it and serialises it back to the browser.
The Unit testing framework makes assertions about a syntax tree for html. Colin showed some html and its parse tree for a simple count-incrementing element. He uses macros, marked by @ ("@macro-name" in html). He did not intend to use the MVC pattern but it fell out so naturally from the work that he accepted it. The macro receives the tag and replaces it with an href (e.g. to a method of his Squeak Seaside application).
He has an @loop tag that creates an invisible parent node for the loop and thence outputs html for each cycle. The loop is a lexical scope for variables. Of course, one could have a Smalltalk loop that generated this code but the aim is to have the right separation between Smalltalk and html as these are written and edited by different people (smalltalkers and designers). The @loop construct lets you avoid writing code to generate html that a designer can just write. He tends to store templates in class-side methods.
Pages are served by the process: template is parsed, macros are expanded, html is served. In the testing case, the third stage is replaced by assertions on what is served. Tests can
- check that actions are bound to tags (checked via verifying that something somewhere in page is bound via callbacks)
- check that action has required effect (do action then check via verifying that returned value is somewhere on page)
Colin demoed both the above cases on a simple increment method: that it was bound, that the right initial and incremented values were on the page at the right stages. His tests simply verified that certain literals were anywhere on the page. The view classes have do: methods to iterate over their contents so tag-based tests can be quite detailed.
Q. (Niall) I have found that testing UIs via tests that exercise model functions through the UI are much less brittle than test point-and-click. This approach carries that idea to the extreme in that you don't check anything about the page's appearance, just that the right methods and values are in the served html. Should it be supplemented by simply printing (or otherwise capturing) the pages and making user look at them, the idea being that if the user likes the look of the pages then your tests, if all run green, ensure that nothing else can be wrong?
A. (Colin) The intent of tests enabled by this approach is to verify that the dynamic state of application matches the state of code. It says nothing about whether the html is white on a white background or similarly unusable for purely visual reasons. Any such bugs would have to be caught otherwise but, as you suggest, should be trivial to find and fix.