Strategies For Testing Ajax

Author: Kumar McMillan
Company:Leapfrog Online, LLC
Duration:30 Minutes

Agenda

Why create automated tests?

My Background

Testing Ajax is hard

Testing Ajax is easy

Example: aintjustsoul.net

aintjustsoul.net

images/aintjustsoul.png

Server Sends JSON To UI

GET /auctions.json
{
    "images": [{
        "height": 60,
        "width": 80,
        "auction_id": 28465,
        "path": "http://.../images/59831.jpg"
    }, {
        ...
    }]
}

Strategy #1

1 . Test Data Handlers

2 . Test JavaScript

3 . Isolate UI For Testing

4 . Automate UI Tests

5 . Gridify your test suite

Python HTTP get test

def test_auction_images():
    response = app.get("/auctions.json")
    json = simplejson.loads(response.body)
    assertEqual(
        json['images'][0]['auction_id'],
        28465 )
    # etc...

Python HTTP GET test

In action!

Python HTTP GET test

images/aintjustsoul-data-test.png

Strategy #2

1 . Test Data Handlers

2 . Test JavaScript

3 . Isolate UI For Testing

4 . Automate UI Tests

5 . Gridify your test suite

Check For Lint

http://javascriptlint.com/

$ jsl -process ./js/cool-ajax.js
cool-ajax.js(41): trailing comma is not legal
var conf = {debug: true,};
........................^

0 error(s), 1 warning(s)

Run Unit Tests With Rhino

http://www.mozilla.org/rhino/

java -jar js.jar ./your_test_runner.js

Run Unit Tests With Rhino

http://www.mozilla.org/rhino/

java -jar js.jar ./your_test_runner.js

Run Unit Tests With Rhino

http://www.mozilla.org/rhino/

java -jar js.jar ./your_test_runner.js

Dojo's Unit Tests in Rhino

In action!

Dojo's Unit Tests in Rhino

images/dojo-rhino-tests.png

Run Unit Tests In A Browser

http://localhost/app/run-tests.html

Unit Tests For Fudge

Unit Tests For Fudge

images/fudge-unit-tests.png

jQuery QUnit Example

<script src="qunit/testrunner.js"></script>
<script type="text/javascript">
module("Ajax navigation");

test("go() sets hash", function() {
    nav.go("#somewhere");
    equals(window.location.hash,
           "#somewhere");
});

Here's Where It Gets Tricky

images/tight-rope-bigger.jpg

Strategy #3

1 . Test Data Handlers

2 . Test JavaScript

3 . Isolate UI For Testing

4 . Automate UI Tests

5 . Gridify your test suite

Example Ajax application

images/ajax-webapp.png

Isolate UI For Testing

images/ajax-ui-isolated.png

Aintjustsoul UI, Isolated

In action!

Aintjustsoul UI, Isolated

images/aintjustsoul-dev-ui.png

Using a fake server

if config['ui.enable_test'] == True:
    map.connect('/auctions.json',
        controller='_ui_test_/browse',
        action='auctions')
else:
    map.connect('/auctions.json',
        controller='browse',
        action='auctions')

# ...

UI Layer Doesn't Know

dojo.xhrGet({
    url: "/auctions.json",
    handleAs: "json",
    load: function(response) {
        images.load(response.images);
        // etc...
    }
});

Using a fake server

Advantages :

Using a fake server

Disadvantages :

Bypass Server Altogether

jQuery.extend({
    ajax: function( ajax ) {
        switch (ajax.url) {
            case '/auctions.json':
                ajax.success({images:[]});
                break;
            default:
                ajax.error("Unexpected URL");
        }
    }
});

Strategy #4

1 . Test Data Handlers

2 . Test JavaScript

3 . Isolate UI For Testing

4 . Automate UI Tests

5 . Gridify your test suite

Selenium Remote Control

def test_click_auction_image():
    selenium.open("/")
    selenium.click("auction-1")
    assertEqual(
        selenium.get_text("css=#details h1"),
        'Rare James Brown 45'
    )
    # etc ...

Selenium Remote Control

In action!

Selenium Remote Control

images/aintjustsoul-selenium.png

Web Browser Automation Tools

Strategy #5

1 . Test Data Handlers

2 . Test JavaScript

3 . Isolate UI For Testing

4 . Automate UI Tests

5 . Gridify your test suite

Gridify your tests

images/selenium-tests-in-serial.png

Gridify your tests

images/selenium-tests-in-parallel.png

Gridify your tests

Future?

Recap of Ajax testing strategies

  1. Test Data Handlers
    • HTTP Request / Response
  2. Test JavaScript
    • Check for lint
    • Using Rhino or a web browser
  3. Isolate UI For Testing
    • Fake server or JavaScript stubs
  4. Automate UI Tests
    • Selenium, etc
  5. Gridify your test suite

Wrap-up