Automated javascript unit testing
Upcoming SlideShare
Loading in...5
×
 

Automated javascript unit testing

on

  • 10,047 views

 

Statistics

Views

Total Views
10,047
Views on SlideShare
10,047
Embed Views
0

Actions

Likes
6
Downloads
56
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Automated javascript unit testing Automated javascript unit testing Presentation Transcript

    • Automated Javascript Unit Testing Ryan Chambers [email_address] Intelliware Development
    • 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
    • Testing Goals
      • Easy to develop tests in eclipse
      • Tests runnable as part of maven build
      • Fast
      • Cross-browser
    • 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
    • Code to be tested
      • var validation = function () {
      • return {
      • validateAlphaNumeric: function (field) {..},
      • validateUsername : function (field) {
      • $.ajax({…});
      • }
      • }
      • }
    • 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/
    • Test Code
      • TestCase("validateAlphaNumeric", {
      • "test validateAlphaNumeric valid" : function() {
      • /*:DOC input = <input type=&quot;text&quot; id=&quot;test_field&quot; value=&quot;aB1&quot; /> */
      • var field = $(this.input),
      • isValid;
      • isValid = validation.validateAlphaNumeric(field);
      • assertEquals(&quot;aB1 should be valid&quot;, true, isValid);
      • },
      • &quot;test validateAlphaNumeric invalid&quot; : function() {
      • /*:DOC input = <input type=&quot;text&quot; id=&quot;test_field&quot; value=&quot;!&quot; /> */
      • var field = $(this.input),
      • isValid;
      • isValid = validation.validateAlphaNumeric(field);
      • assertEquals(&quot;! is not valid alphanumeric value&quot;, false, isValid);
      • }
      • });
    • Sinon.JS
      • A library for standalone test spies, stubs and mocks
      • Can also fake XHR (AJAX) and servers
      • http:// sinonjs.org /
    • Testing AJAX with SinonJS
      • TestCase(&quot;validateUsername&quot;, sinon.testCase({
        • setUp : function() {
        • validation.reset();
        • this.server = sinon.fakeServerWithClock.create();
        • /*:DOC input = <input type=&quot;text&quot; id=&quot;test_field&quot; value=&quot;!&quot; /> */
        • },
        • tearDown: function() {
        • this.server.restore();
        • },
        • &quot;test validateUsername user name already used&quot; : function() {
          • var field = $(this.input), isValid;
          • this.server.respondWith(createFakeResponse('error : username already used'));
          • isValid = callValidation(field, this.server);
          • assertEquals(&quot;should have got username already used error&quot;, isValid, false);
        • }
      • }
    • Testing AJAX with SinonJS
      • function createFakeResponse(responseCode) {
      • return [
      • 200,
      • { &quot;Content-Type&quot;: &quot;text/xml&quot; },
      • '<?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?> <result>' + responseCode + '</result>'
      • ];
      • }
      • function callValidation(field, server) {
      • validation.validateUsername(field);
      • server.respond();
      • return validation.validateAlphaNumeric(field);
      • }
    • JS Test Runner Demo
      • Demo of eclipse plug-in
      • Demo of maven build
      • https://github.com/ryan-chambers/jstestdriver-sample-project
    • 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 tests
      • https:// github.com/jquery/qunit
    • QUnit Test page
      • Includes all required css and javascript
      • Adds elements to DOM that are required for test
      • <input type= &quot;text&quot; id= &quot;test_field&quot; value= &quot;!&quot; />
    • QUnit Tests - setup
      • module(&quot;validation&quot;, {
      • setup : function () {
      • this.field = $('#test_field');
      • validation.reset();
      • },
      • tearDown: function () {
      • this .xhr.restore();
      • }
      • });
    • QUnit Tests
      • test(&quot;validateAlphaNumeric invalid&quot;, function () {
      • this.field.val('!');
      • var isValid = validation.validateAlphaNumeric(
      • this.field);
      • equal(isValid, false , &quot;! Should
      • not be a valid alphanumeric
      • value&quot;);
      • });
    • QUnit Tests with SinonJS
      • function testFakeUserValidationWithResponse(responseCode, testHandler) {
      • var server = sinon.fakeServerWithClock.create();
      • try {
      • server.respondWith([
      • 200,
      • { &quot;Content-Type&quot;: &quot;text/xml&quot; },
      • '<?xml version=&quot;1.0&quot; encoding=&quot;UTF- 8&quot;?><result>‘
      • + responseCode + '</ result >'
      • ]);
      • testHandler(server);
      • } finally {
      • server.restore();
      • }
      • }
    • QUnit tests with SinonJS
      • test(&quot;validateUsername user name already used&quot;, function (
      • {
      • var that = this;
      • testFakeUserValidationWithResponse(username_ already_used', function (server) {
      • validation.validateUsername(that.field);
      • server.respond();
      • var isUsernameValid = validation.isUsernameValid();
      • equal(isUsernameValid, false , &quot;should have got
      • username already used error&quot;);
      • });
      • });
    • Selenium
      • public class ValidationIntegrationTest {
      • private WebDriver driver;
        • @Before
        • public void setUp() throws Exception {
        • driver = new FirefoxDriver();
        • }
        • @Test
        • public void testFormsIntegration() throws Exception {
          • driver.get(&quot;http://localhost:8080/validation.html&quot;);
          • assertPageIsLoaded();
          • List<WebElement> failedElements = driver.findElements(By. xpath (&quot;//span[@class='fail']&quot;));
          • // could do more here to return failure messages
          • Assert. assertEquals (0, failedElements.size());
        • }
        • private void assertPageIsLoaded() {
        • driver.findElement(By. id (&quot;qunit-header&quot;));
        • }
        • @After
        • public void tearDown() throws Exception {
        • driver.close();
        • }
      • }
    • QUnit demo
      • View page in browser
      • Run unit test in eclipse w/ Jetty
      • https://github.com/ryan-chambers/qunit-selenium-sample-project
    • 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
    • Jasmine Specs
      • describe('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('ab@google.com');
      • expect(isValidAlphaNumeric).toEqual( false );
      • });
      • });
    • 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
    • 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 /
    • JS Test Runner
      • @RunWith(JSTestSuiteRunner. class )
      • @JSTestSuiteRunner.Include(value=&quot;validation.html&quot;)
      • public class ValidationJSTest {
      • }
    • QUnit, PhantomJS and JS Test Runner
      • Run unit tests from Eclipse
      • Run build from maven
      • https://github.com/ryan-chambers/jstest-runner-sample-project
    • Questions?