#reader(lib "docreader.ss" "scribble") @require[(file "base.ss")] @title{Introduction} @section{What is Delirium?} Delirium is a tool for testing PLT web application user interfaces. It allows programmers to write tests with unprecedented clarity and speed. Delirium is built on top of SchemeUnit and the PLT Web Server. Web interface testing is difficult because you need to control the server and the browser at the same time. Delirium gives you the ability to write a single SchemeUnit script that does both in a single test script. There is very little configuration involved (especially if you are using the @seclink["instaweb/delirium"]{Instaweb} @PLaneT package) and you won't need to write a lick of Javascript. Here is an example test case that tests a login page for a simple web application: @schemeblock[ (test-case "Users can log in via the login page" (code:comment "The test database starts off empty: we need a new user:") (let ([user (make-user #:username "dave" #:password "password")] [now (current-milliseconds)]) (code:comment "Save the user to the database:") (save! user) (code:comment "Open the login page in the browser and wait for the page refresh:") (open/wait "/login") (code:comment "Fill in the login form in the browser:") (type (node/id 'username-field "dave")) (code:comment "Type in the username") (type (node/id 'password-field "password")) (code:comment "Type in the password") (code:comment "Click 'Submit' and wait for the page to refresh:") (click/wait 'submit-button) (code:comment "Check the page title is 'Welcome, dave!'") (check-equal? (title-ref) "Welcome, dave!") (code:comment "Check the login was recorded:") (check > (user-last-login user) now)))] This is a standard SchemeUnit test-case being run by the Delirium framework. The code used comes from three sources: @itemize{ @item{Delirium tests are defined on the server, so they have access to all the library code used in the web application being tested. The @scheme[make-user], @scheme[save!] and @scheme[user-last-login] in the example are all imported from the application itself.} @item{Delirium is built on top of SchemeUnit, which provides a rich testing framework. The @scheme[test-case], @scheme[check] and @scheme[check-equal?] forms in the example are standard procedures and macros from SchemeUnit.} @item{Delirium provides an API for remote-controlling the web browser. The @scheme[open/wait], @scheme[click/wait], @scheme[node/id], @scheme[type] and @scheme[title-ref] procedures in the example work by remotely executing Javascript code on the browser and returning the results.}} Note that, like SchemeUnit tests, Delirium tests are all fully fledged Scheme code: you can use all the abstractions that you would expect, including loops, conditionals, procedures and macros. Gone are the days of writing tests as an HTML table! @section{How does it work?} Delirium only works on web applications created for the PLT Web Server. You set up your application so it can be run in two different modes: @itemize{ @item{@italic{Production mode} bypasses all of the Delirium setup and simply runs your application.} @item{@italic{Test mode} runs your application with whatever external resources (databases, configuration files, user credentials) you need for testing, and sets up a special @italic{test servlet} that runs Delirium.}} Here is an example start procedure from a test servlet: @schemeblock[ (code:comment "start : request -> response") (define (start request) (code:comment "run-delirium : request schemeunit-test-suite -> response") (run-delirium request my-ui-test-suite))] The test servlet is typically mapped to a URL like @scheme{http://localhost:8000/test}. When the servlet is invoked, @scheme[run-delirium] will send a test-page to the browser. The test-page contains an @italic{iframe}, to which all browser API calls like @scheme[open/wait] are directed. All the test suite has to do is call @scheme[open/wait] on the relevant part of the web application. Delirium uses continuations to maintain a REPL-style testing loop: @itemize{ @item{Run the test code until a browser API call is made.} @item{Send the command to the browser.} @item{Wait for a result from the browser.} @item{Return the result to the test code and loop.}} Commands are sent to the browser as fragments of Javascript. Results are sent back in JSON format and are parsed into Scheme data structures. @section[#:tag "instaweb/delirium"]{Using Delirium with Instaweb} Delirium has been built specifically to work with version 2 of the @link[url:schematics/instaweb.plt]{Instaweb} @PLaneT package. Simply change your Instaweb import statement from: @schemeblock[(planet "instaweb.ss" ("schematics" "instaweb.plt" 2))] to: @schemeblock[(planet "instaweb.ss" ("untyped" "delirium.plt" 2))] and change your call to @scheme[instaweb] to a call to @scheme[instaweb/delirium]. This procedure takes a few extra arguments that let you configure the test-suite to run and choose production mode or test mode. In test mode, @scheme[instaweb/delirium] automatically sets up the test servlet and Delirium's Javascript libraries: it can even open the test page automatically in your web browser.