automated javascript unit testing

26
Automated Javascript Unit Testing Ryan Chambers ryan.chambers@intelliware .ca Intelliware Development

Upload: ryanchambers

Post on 06-May-2015

10.141 views

Category:

Technology


5 download

TRANSCRIPT

Page 1: Automated javascript unit testing

Automated Javascript Unit Testing

Ryan Chambers

[email protected]

Intelliware Development

Page 2: Automated javascript unit testing

Outline

• Why should I write javascript tests?

• Testing goals

• The code we’re going to test

• How can I automate the tests?– JS Test Driver– QUnit and Selenium– Jasmine Maven Plugin– QUnit, PhantomJS and JS Test Runner

Page 3: Automated javascript unit testing

Testing Goals

1. Easy to develop tests in eclipse

2. Tests runnable as part of maven build

3. Fast

4. Cross-browser

Page 4: Automated javascript unit testing

Why write javascript unit tests?

• Why write java tests?

• Faster to test unit tests than to browse actual application

• Can help find new bugs

• Easy to add to part of build process, giving you another layer of testing

Page 5: Automated javascript unit testing

Code to be tested

var validation = function() {… return { validateAlphaNumeric: function(field) {..}, validateUsername : function (field) { $.ajax({…}); } }}

Page 6: Automated javascript unit testing

JS Test Driver• Project from google to automate javascript testing• Provides a javascript unit testing framework• Maven plug-in and eclipse plug-in• Uses real browsers

– However, I had problems with Chrome– Browsers weren’t always closed after

• No need to create fixture html – but you can specify html in each test

• Server isn’t needed unless for AJAX• Has a QUnit adapter• Some flakiness, nothing I could reproduce reliably but I felt like

it did weird stuff sometimes• http://code.google.com/p/js-test-driver/

Page 7: Automated javascript unit testing

Test CodeTestCase("validateAlphaNumeric", {

"test validateAlphaNumeric valid" : function() { /*:DOC input = <input type="text" id="test_field" value="aB1" /> */

var field = $(this.input),isValid;

isValid = validation.validateAlphaNumeric(field);assertEquals("aB1 should be valid", true, isValid);

},"test validateAlphaNumeric invalid" : function() {

/*:DOC input = <input type="text" id="test_field" value="!" /> */var field = $(this.input),

isValid;isValid = validation.validateAlphaNumeric(field);assertEquals("! is not valid alphanumeric value", false,

isValid);}

});

Page 8: Automated javascript unit testing

Sinon.JS

• A library for standalone test spies, stubs and mocks

• Can also fake XHR (AJAX) and servers

• http://sinonjs.org/

Page 9: Automated javascript unit testing

Testing AJAX with SinonJSTestCase("validateUsername", sinon.testCase({

setUp : function() {validation.reset();this.server = sinon.fakeServerWithClock.create();

/*:DOC input = <input type="text" id="test_field" value="!" /> */

},tearDown: function() { this.server.restore();},"test validateUsername user name already used" : function() {

var field = $(this.input), isValid;this.server.respondWith(createFakeResponse('error : username

already used'));isValid = callValidation(field, this.server);assertEquals("should have got username already used error",

isValid, false);}

}

Page 10: Automated javascript unit testing

Testing AJAX with SinonJSfunction createFakeResponse(responseCode) { return [ 200, { "Content-Type": "text/xml" }, '<?xml version="1.0" encoding="UTF-8"?>

<result>' + responseCode + '</result>'];

}

function callValidation(field, server) {validation.validateUsername(field);server.respond();return validation.validateAlphaNumeric(field);

}

Page 11: Automated javascript unit testing

JS Test Runner Demo

• Demo of eclipse plug-in• Demo of maven build

https://github.com/ryan-chambers/jstestdriver-sample-project

Page 12: Automated javascript unit testing

QUnit and Selenium

• QUnit is a javascript testing library originally written to test jQuery

• Selenium tests using real browsers– very slow– Typically only one browser is tested

• Meant for automated testing of page flows, not javascript unit testing

• I wrote a sample test that only records whether all tests pass or not– could possibly be updated to record actual error

• Requires creating an html page to host testshttps://github.com/jquery/qunit

Page 13: Automated javascript unit testing

QUnit Test page

• Includes all required css and javascript

• Adds elements to DOM that are required for test

<input type="text" id="test_field" value="!" />

Page 14: Automated javascript unit testing

QUnit Tests - setup

module("validation", {setup : function() {

this.field = $('#test_field'); validation.reset();

},tearDown: function () {

this.xhr.restore(); }});

Page 15: Automated javascript unit testing

QUnit Tests

test("validateAlphaNumeric invalid", function() {

this.field.val('!');var isValid =

validation.validateAlphaNumeric(this.field);

equal(isValid, false, "! Shouldnot be a valid alphanumericvalue");

});

Page 16: Automated javascript unit testing

QUnit Tests with SinonJSfunction testFakeUserValidationWithResponse(responseCode,

testHandler) {var server = sinon.fakeServerWithClock.create();try {

server.respondWith([ 200, { "Content-Type": "text/xml" }, '<?xml version="1.0" encoding="UTF-

8"?><result>‘ + responseCode + '</ result >' ]);

testHandler(server); } finally { server.restore(); }}

Page 17: Automated javascript unit testing

QUnit tests with SinonJStest("validateUsername user name already used", function(

{var that = this;testFakeUserValidationWithResponse(username_already_used', function(server) {

validation.validateUsername(that.field);

server.respond();

var isUsernameValid = validation.isUsernameValid(); equal(isUsernameValid, false, "should have got

username already used error");});

});

Page 18: Automated javascript unit testing

Seleniumpublic class ValidationIntegrationTest {

private WebDriver driver;

@Beforepublic void setUp() throws Exception {

driver = new FirefoxDriver();}

@Testpublic void testFormsIntegration() throws Exception {

driver.get("http://localhost:8080/validation.html");assertPageIsLoaded();List<WebElement> failedElements = driver.findElements(By.xpath("//span[@class='fail']"));// could do more here to return failure messagesAssert.assertEquals(0, failedElements.size());

}

private void assertPageIsLoaded() {driver.findElement(By.id("qunit-header"));

}

@Afterpublic void tearDown() throws Exception {

driver.close();}

}

Page 19: Automated javascript unit testing

QUnit demo

• View page in browser• Run unit test in eclipse w/ Jetty

https://github.com/ryan-chambers/qunit-selenium-sample-project

Page 20: Automated javascript unit testing

Jasmine Maven Plug-in

• Jasmine is a BDD javascript unit test framework– You create a “spec” in a DSL that almost looks like English– BDD is very popular in Ruby on Rails

• https://github.com/pivotal/jasmine/wiki

• Jasmine maven plug-in looks in certain directories for tests and their specs– Can configure includes for libraries (eg. Jasmine/sinon plug-in)– Uses HTMLUnit for DOM

• https://github.com/searls/jasmine-maven-plugin

Page 21: Automated javascript unit testing

Jasmine Specsdescribe('validation', function() { it('should detect valid alphanumeric sequences',

function() {var isValidAlphaNumeric =

validation.isAlphaNumeric('aA1');expect(isValidAlphaNumeric).toEqual(true);

});

it('should detect invalid alphanumeric sequences', function() {

var isValidAlphaNumeric = validation.isAlphaNumeric('[email protected]');

expect(isValidAlphaNumeric).toEqual(false); });});

Page 22: Automated javascript unit testing

Jasmine Maven Plug-in demo

• Run tests in browser– mvn jasmine:bdd– http://localhost:8234

• Run maven build

https://github.com/ryan-chambers/maven-jasmine-sample-project

Page 23: Automated javascript unit testing

QUnit, PhantomJS and JS Test Runner

• PhantomJS is a command-line tool that embeds WebKit and can run javascript– Very fast, since there is no browser

http://www.phantomjs.org/

• JS Test Runner is a JUnit test runner that uses QUnit and Phantomjs for javascript– Runnable from maven and eclipse

http://js-testrunner.codehaus.org/

Page 24: Automated javascript unit testing

JS Test Runner

@RunWith(JSTestSuiteRunner.class)

@JSTestSuiteRunner.Include(value="validation.html")

public class ValidationJSTest {

}

Page 25: Automated javascript unit testing

QUnit, PhantomJS and JS Test Runner

• Run unit tests from Eclipse• Run build from maven

https://github.com/ryan-chambers/jstest-runner-sample-project

Page 26: Automated javascript unit testing

Questions?