root/misc/ep2006.html

Revision 56 (checked in by johnny, 6 years ago)

Some small updates.

Line 
1 <html>
2   <head>
3     <title>SlideShow</title>
4     <link type="text/css" rel="stylesheet" href="slideshow/slideshow.css" />
5     <script type="text/javascript" src="slideshow/jsbase/misclib.js"></script>
6     <script type="text/javascript" src="slideshow/jsbase/testing.js"></script>
7     <script type="text/javascript" src="slideshow/slideshow.js"></script>
8   </head>
9   <body onload="slideshow.INCLUDE_FRONTPAGE_AS_SLIDE = true;
10                 slideshow.initialize(document, 'slide', 'slides', 'slidenum',
11                                         'numslides')">
12     <div id="slide" title="hypertest">
13       <h3>HyperTest</h3>
14       <div class="textbody">
15         <div>Guido Wesdorp</div>
16         <div>EuroPython 2006</div>
17         <div>guido@merlinux.de</div>
18       </div>
19     </div>
20     <div id="slides">
21       <div title="introduction">
22         <h3>Introduction</h3>
23         <div class="body">
24           <ul>
25             <li>More JavaScript! :|</li>
26             <li>EcmaUnit, HTTPUnit, AppTest</li>
27             <li>Python command-line test runner</li>
28             <li>Open source (BSD-style license)</li>
29           </ul>
30         </div>
31       </div>
32       <div title="existing solutions">
33         <h3>Existing solutions</h3>
34         <div class="body">
35           <ul>
36             <li>Unit test suites</li>
37             <li>JSUnit - not OO, messy, lot of globals</li>
38             <li>Functional testing</li>
39             <li>Selenium - strange (tables), restrictive</li>
40             <li>Haven't seen everything yet...</li>
41           </ul>
42         </div>
43       </div>
44       <div title="ecmaunit">
45         <h3>EcmaUnit - unit tests</h3>
46         <div class="body">
47           <ul>
48             <li>Written for Kupu</li>
49             <li>Traditional unit test API, like Python's 'unittest'</li>
50             <li>May be changed later, made simpler</li>
51             <li>Also works in SpiderMonkey</li>
52           </ul>
53         </div>
54       </div>
55       <div title="ecmaunit example">
56         <h3>EcmaUnit example</h3>
57 <!-- Trac blob ahead! -->
58
59 <div class="code"><pre>
60 <B><span class="code-lang">function</span></B> <B><span class="code-func">ExampleTestCase</span></B>() {
61     <I><span class="code-comment">/* an example unit test */</span></I>
62     <B><span class="code-lang">this</span></B>.name = <B><span class="code-string">'ExampleTestCase'</span></B>;
63
64     <I><span class="code-comment">// this method will be executed before *every* test
65 </span></I>    <I><span class="code-comment">// method, there's also a tearDown counterpart that
66 </span></I>    <I><span class="code-comment">// is not used in this example
67 </span></I>    <B><span class="code-lang">this</span></B>.setUp = <B><span class="code-lang">function</span></B>() {
68         <B><span class="code-lang">function</span></B> <B><span class="code-func">Foo</span></B>() {
69             <B><span class="code-lang">this</span></B>.returnfoo = <B><span class="code-lang">function</span></B>() {
70               <B><span class="code-lang">return</span></B> <B><span class="code-string">'foo'</span></B>;
71             };
72             <B><span class="code-lang">this</span></B>.throwfoo = <B><span class="code-lang">function</span></B>() {
73               <B><span class="code-lang">throw</span></B>(<B><span class="code-string">'foo'</span></B>);
74             };
75         };
76         <B><span class="code-lang">this</span></B>.foo = <B><span class="code-lang">new</span></B> Foo();
77     };
78
79     <I><span class="code-comment">// an example of a successful assertEquals call
80 </span></I>    <B><span class="code-lang">this</span></B>.testAssertEquals = <B><span class="code-lang">function</span></B>() {
81         <B><span class="code-lang">this</span></B>.assertEquals(<B><span class="code-lang">this</span></B>.foo.returnfoo(), <B><span class="code-string">'foo'</span></B>);
82     };
83
84     <I><span class="code-comment">// an example of a successful assertThrows call (to
85 </span></I>    <I><span class="code-comment">// test whether some call results in an exception)
86 </span></I>    <B><span class="code-lang">this</span></B>.testAssertThrows = <B><span class="code-lang">function</span></B>() {
87         <B><span class="code-lang">this</span></B>.assertThrows(<B><span class="code-lang">this</span></B>.foo.throwfoo, <B><span class="code-string">'foo'</span></B>);
88     };
89 };
90
91 <I><span class="code-comment">// each test case has to subclass from TestCase, which provides
92 </span></I><I><span class="code-comment">// the .assert* methods and some stubs
93 </span></I>ExampleTestCase.prototype = <B><span class="code-lang">new</span></B> TestCase;
94 </pre></div>
95
96 <!-- end Trac blob 1 -->
97
98       </div>
99       <div title="ecmaunit running example">
100         <h3>EcmaUnit running</h3>
101         <iframe class="bodyframe" loadsrc="http://johnnydebris.net:8080/projects/hypertest/js/ecmaunit/testecmaunit.html"></iframe>
102       </div>
103       <div title="httpunit">
104         <h3>HTTPUnit - testing HTTP APIs</h3>
105         <div class="body">
106           <ul>
107             <li>Uses XMLHttpRequest</li>
108             <li>Examine returned headers and body</li>
109             <li>Test with real clients</li>
110             <li>Can mostly be replaced with server-side tests,</li>
111             <li>but can be useful in some cases</li>
112           </ul>
113         </div>
114       </div>
115       <div title="httpunit example">
116         <h3>HTTPUnit example</h3>
117 <!-- more Trac blob -->
118
119 <div class="code"><pre><I><span class="code-comment">// a simple test function, assumes there's a cgi script called 'square.cgi' in
120 </span></I><I><span class="code-comment">// the root of the proxy which returns 4 if a POST body 'int=16' is inputted,
121 </span></I><I><span class="code-comment">// if this fails, an error is reported and the next test is called
122 </span></I><B><span class="code-lang">function</span></B> <B><span class="code-func">test_square_root</span></B>(testcase, status, headers, body) {
123     testcase.assertEquals(status, <B><span class="code-string">'200'</span></B>);
124     testcase.assertEquals(headers[<B><span class="code-string">'content-type'</span></B>].substr(0, 10),
125                             <B><span class="code-string">'text/plain'</span></B>);
126     <I><span class="code-comment">// note that string.strip() is a function of the 'jsbase' library
127 </span></I>    testcase.assertEquals(string.strip(body), <B><span class="code-string">'4'</span></B>);
128 };
129
130 <I><span class="code-comment">// register the function so it can be ran later
131 </span></I>window.httpunit_test_registry.push([
132     test_square_root, <I><span class="code-comment">// test function
133 </span></I>    <B><span class="code-string">'/square_root.cgi'</span></B>, <I><span class="code-comment">// url to test
134 </span></I>    <B><span class="code-string">'POST'</span></B>, <I><span class="code-comment">// method
135 </span></I>    {<B><span class="code-string">'Content-Type'</span></B>: <B><span class="code-string">'application/x-www-form-urlencoded'</span></B>}, <I><span class="code-comment">// headers
136 </span></I>    <B><span class="code-string">'int=16'</span></B> <I><span class="code-comment">// body
137 </span></I>]);
138 </pre></div>
139
140 <!-- end Trac blob -->
141       </div>
142       <div title="httpunit running example">
143         <h3>HTTPUnit running</h3>
144         <iframe class="bodyframe" loadsrc="http://johnnydebris.net:8080/projects/hypertest/js/httpunit.js/run_tests.html"></iframe>
145       </div>
146       <div title="apptest">
147         <h3>AppTest - functional tests</h3>
148         <div class="body">
149           <ul>
150             <li>Sequence of user actions</li>
151             <li>'Lower level' functional testing framework</li>
152             <li>Simple framework with some helper functions</li>
153             <li>More (higher level) helper stuff coming up</li>
154           </ul>
155         </div>
156       </div>
157       <div title="apptest example">
158         <h3>AppTest example</h3>
159
160 <!-- and another one... -->
161
162 <div class="code"><pre><B><span class="code-lang">function</span></B> <B><span class="code-func">test_sync</span></B>(at, browser) {
163     <I><span class="code-comment">/* simple test of a plain HTML document */</span></I>
164     <I><span class="code-comment">// see whether the title is what we expect; if this fails (or
165 </span></I>    <I><span class="code-comment">// any other at.assert* call), execution of the test chain
166 </span></I>    <I><span class="code-comment">// stops entirely
167 </span></I>    at.assertEquals(browser.title,
168                             <B><span class="code-string">'Test document 1'</span></B>);
169
170     <I><span class="code-comment">// also test the content of the 'body' element
171 </span></I>    at.assertEquals(
172         string.strip(
173             browser.document.getElementsByTagName(
174                 <B><span class="code-string">'body'</span></B>
175             )[0].childNodes[0].nodeValue
176         ),
177         <B><span class="code-string">'Test document content'</span></B>
178     );
179
180     <I><span class="code-comment">// in the end we have to make sure we send the browser to the
181 </span></I>    <I><span class="code-comment">// next location, either by clicking a button or by setting a new
182 </span></I>    <I><span class="code-comment">// location (unless this is the last test, in that case nothing
183 </span></I>    <I><span class="code-comment">// special needs to be done)
184 </span></I>    browser.navigateTo(<B><span class="code-string">'apptestdata/test_async.html'</span></B>);
185 };
186
187 window.app_test_registry.push([<B><span class="code-string">'apptestdata/test_sync.html'</span></B>, test_sync]);
188 </pre></div>
189
190 <!-- end -->
191
192       </div>
193       <div title="ajax testing">
194         <h3>AJAX - hard to test</h3>
195         <div class="body">
196           <ul>
197             <li>Outside of main loops or function bodies</li>
198             <li>So no error catching</li>
199             <li>No sleep() or tight loops, block the interpreter</li>
200             <li>Polling or callbacks</li>
201           </ul>
202         </div>
203       </div>
204       <div title="async apptest">
205         <h3>Asynchronous AppTest</h3>
206         <div class="body">
207           <ul>
208             <li>Return special token, continue outside of test function body</li>
209             <li>Navigate away *and* call callback when done</li>
210             <li>Users have to do their own error handling</li>
211             <li>No way around those issues (afaik?), but at least it works!</li>
212           </ul>
213         </div>
214       </div>
215       <div title="async apptest example">
216         <h3>Async AppTest example</h3>
217 <!-- ... -->
218
219 <div class="code"><pre>
220 <I><span class="code-comment">// simple polling loop that continues testing
221 </span></I><B><span class="code-lang">var</span></B> poll_and_continue = <B><span class="code-lang">function</span></B>(at, browser, callback, orgtext) {
222     <B><span class="code-lang">var</span></B> newtext = browser.getText(
223         browser.document.getElementById(<B><span class="code-string">'container'</span></B>)
224     );
225     <I><span class="code-comment">// check if the text has been updated yet
226 </span></I>    <B><span class="code-lang">if</span></B> (newtext == orgtext) {
227         <I><span class="code-comment">// not yet updated, poll
228 </span></I>        misclib.schedule(<B><span class="code-lang">this</span></B>, poll_and_continue, 100, at, browser, callback, orgtext);
229         <B><span class="code-lang">return</span></B>;
230     };
231     at.assertEquals(string.strip(newtext), <B><span class="code-string">'Text loaded'</span></B>);
232
233     callback();
234 };
235
236 <B><span class="code-lang">function</span></B> <B><span class="code-func">test_async</span></B>(at, browser, callback) {
237     <I><span class="code-comment">/* we have a document with a div that is filled with data, using
238         XMLHttpRequest, after pressing some button...
239     */</span></I>
240
241     <I><span class="code-comment">// first we store the original text
242 </span></I>    <B><span class="code-lang">var</span></B> orgtext = browser.getText(
243         browser.document.getElementById(<B><span class="code-string">'container'</span></B>)
244     );
245     <I><span class="code-comment">// see whether it's the text we expect
246 </span></I>    at.assertEquals(
247         string.strip(orgtext),
248         <B><span class="code-string">'Nothing to see here, please move along.'</span></B>
249     );
250
251     <I><span class="code-comment">// click the button that starts the XHR text loading
252 </span></I>    browser.getElementsByText(<B><span class="code-string">'load'</span></B>)[0].click();
253
254     <I><span class="code-comment">// start the polling and continue testing there
255 </span></I>    poll_and_continue(at, browser, callback, orgtext);
256
257     <I><span class="code-comment">// tell the framework to wait until the callback is called
258 </span></I>    <B><span class="code-lang">return</span></B> at.CONTINUE_ASYNC;
259 };
260
261 window.app_test_registry.push([<B><span class="code-string">'apptestdata/test_async.html'</span></B>, test_async]);
262 </pre></div>
263
264 <!-- i think this is it for now... -->
265       </div>
266       <div title="apptest running example">
267         <h3>AppTest running</h3>
268         <iframe class="bodyframe" loadsrc="http://johnnydebris.net:8080/projects/hypertest/js/apptest/testtest.html"></iframe>
269       </div>
270       <div title="hypertest combines">
271         <h3>HyperTest combines</h3>
272         <div class="body">
273           <ul>
274             <li>Run all the tests from one page</li>
275             <li>One reporter</li>
276             <li>Similar registration for all tests</li>
277             <li>(Somewhat) consistent API</li>
278           </ul>
279         </div>
280       </div>
281       <div title="hypertest running example">
282         <h3>HyperTest running</h3>
283         <iframe class="bodyframe" loadsrc="http://johnnydebris.net:8080/projects/hypertest/htdocs/run_tests.html"></iframe>
284       </div>
285       <div title="browsertest">
286         <h3>BrowserTest test runner</h3>
287         <div class="body">
288           <ul>
289             <li>Python script</li>
290             <li>Boots (built-in) web server and runs browsers</li>
291             <li>Browser receives tests from server and POSTs results</li>
292             <li>Web server receives and processes results</li>
293             <li>Integration into Python test libs (e.g. py.test)</li>
294           </ul>
295         </div>
296       </div>
297       <div title="browsertest example run">
298         <h3>BrowserTest example output</h3>
299         <pre class="cli">
300 johnny@medusa:~/hypertest$ ./run_browsertest
301 Going to test browser: epiphany
302 TestEcmaUnitTestCase (testecmaunit.js, js test)
303 TestTestCase - testAssert: OK
304 TestTestCase - testAssertEquals: OK
305 TestTestCase - testAssertNotEquals: OK
306 TestTestCase - testAssertTrue: OK
307 TestTestCase - testAssertFalse: OK
308 TestTestCase - testAssertThrows: OK
309 TestTestCase2 - testAssert: OK
310 TestTestCase2 - testAssertEquals: OK
311 TestTestCase2 - testAssertNotEquals: OK
312 TestTestCase2 - testAssertTrue: OK
313 TestTestCase2 - testAssertFalse: OK
314 TestTestCase2 - testAssertThrows: OK
315 time spent: 8 msecs
316
317 TestHTTPUnitTestCase (testhttpunittests.js, http test)
318 TestHTTPUnitTestCase - test_square_root: OK
319 time spent: 75 msecs
320
321 TestAppTestTestCase (testapptests.js, app test)
322 TestAppTestTestCase - apptestdata/test_sync.html: OK
323 TestAppTestTestCase - apptestdata/test_async.html: OK
324 time spent: 439 msecs
325
326 johnny@medusa:~/hypertest$
327         </pre>
328       </div>
329       <div title="py.test">
330         <h3>py.test integration</h3>
331         <div class="body">
332           <ul>
333             <li>Original goal, but not done yet</li>
334             <li>Working on it, though...</li>
335             <li>Unit test integration using SpiderMonkey</li>
336             <li>Full integration with browsertest</li>
337           </ul>
338         </div>
339       </div>
340       <div title="references">
341         <h3>References</h3>
342         <div class="body">
343           <div>http://hypertest.johnnydebris.net</div>
344           <div>http://kupu.oscom.org - EcmaUnit</div>
345           <div>http://codespeak.net/py - py.test</div>
346           <div>guido@merlinux.de</div>
347         </div>
348       </div>
349     </div>
350     <div class="footer">
351       <span id="title">HyperTest - Guido Wesdorp - EuroPython 2006</span>
352       - slide <span id="slidenum">0</span> of <span id="numslides">0</span>
353     </div>
354   </body>
355 </html>
Note: See TracBrowser for help on using the browser.