0
Automated Javascript Unit Testing Ryan Chambers [email_address] Intelliware Development
Outline <ul><li>Why should I write javascript tests? </li></ul><ul><li>Testing goals </li></ul><ul><li>The code we’re goin...
Testing Goals <ul><li>Easy to develop tests in eclipse </li></ul><ul><li>Tests runnable as part of maven build </li></ul><...
Why write javascript unit tests? <ul><li>Why write java tests? </li></ul><ul><li>Faster to test unit tests than to browse ...
Code to be tested <ul><li>var  validation =  function () { </li></ul><ul><li>… </li></ul><ul><li>return { </li></ul><ul><l...
JS Test Driver <ul><li>Project from google to automate javascript testing </li></ul><ul><li>Provides a javascript unit tes...
Test Code <ul><li>TestCase(&quot;validateAlphaNumeric&quot;, { </li></ul><ul><li>&quot;test validateAlphaNumeric valid&quo...
Sinon.JS <ul><li>A library for standalone test spies, stubs and mocks </li></ul><ul><li>Can also fake XHR (AJAX) and serve...
Testing AJAX with SinonJS <ul><li>TestCase(&quot;validateUsername&quot;, sinon.testCase({ </li></ul><ul><ul><li>setUp : fu...
Testing AJAX with SinonJS <ul><li>function createFakeResponse(responseCode) { </li></ul><ul><li>return [ </li></ul><ul><li...
JS Test Runner Demo <ul><li>Demo of eclipse plug-in </li></ul><ul><li>Demo of maven build </li></ul><ul><li>https://github...
QUnit and Selenium <ul><li>QUnit is a javascript testing library originally written to test jQuery </li></ul><ul><li>Selen...
QUnit Test page <ul><li>Includes all required css and javascript </li></ul><ul><li>Adds elements to DOM that are required ...
QUnit Tests - setup <ul><li>module(&quot;validation&quot;, { </li></ul><ul><li>setup :  function () { </li></ul><ul><li>th...
QUnit Tests <ul><li>test(&quot;validateAlphaNumeric invalid&quot;,  function () { </li></ul><ul><li>this.field.val('!'); <...
QUnit Tests with SinonJS <ul><li>function  testFakeUserValidationWithResponse(responseCode, testHandler) { </li></ul><ul><...
QUnit tests with SinonJS <ul><li>test(&quot;validateUsername user name already used&quot;,  function ( </li></ul><ul><li>{...
Selenium <ul><li>public   class  ValidationIntegrationTest { </li></ul><ul><li>private  WebDriver driver; </li></ul><ul><u...
QUnit demo <ul><li>View page in browser </li></ul><ul><li>Run unit test in eclipse w/ Jetty </li></ul><ul><li>https://gith...
Jasmine Maven Plug-in <ul><li>Jasmine is a BDD javascript unit test framework </li></ul><ul><ul><li>You create a “spec” in...
Jasmine Specs <ul><li>describe('validation',  function () { </li></ul><ul><li>it('should detect valid alphanumeric sequenc...
Jasmine Maven Plug-in demo <ul><li>Run tests in browser </li></ul><ul><ul><li>mvn jasmine:bdd </li></ul></ul><ul><ul><li>h...
QUnit, PhantomJS and JS Test Runner <ul><li>PhantomJS is a command-line tool that embeds WebKit and can run javascript </l...
JS Test Runner <ul><li>@RunWith(JSTestSuiteRunner. class ) </li></ul><ul><li>@JSTestSuiteRunner.Include(value=&quot;valida...
QUnit, PhantomJS and JS Test Runner <ul><li>Run unit tests from Eclipse </li></ul><ul><li>Run build from maven </li></ul><...
Questions?
Upcoming SlideShare
Loading in...5
×

Automated javascript unit testing

10,227

Published on

Published in: Technology

Transcript of "Automated javascript unit testing"

  1. 1. Automated Javascript Unit Testing Ryan Chambers [email_address] Intelliware Development
  2. 2. Outline <ul><li>Why should I write javascript tests? </li></ul><ul><li>Testing goals </li></ul><ul><li>The code we’re going to test </li></ul><ul><li>How can I automate the tests? </li></ul><ul><ul><li>JS Test Driver </li></ul></ul><ul><ul><li>QUnit and Selenium </li></ul></ul><ul><ul><li>Jasmine Maven Plugin </li></ul></ul><ul><ul><li>QUnit, PhantomJS and JS Test Runner </li></ul></ul>
  3. 3. Testing Goals <ul><li>Easy to develop tests in eclipse </li></ul><ul><li>Tests runnable as part of maven build </li></ul><ul><li>Fast </li></ul><ul><li>Cross-browser </li></ul>
  4. 4. Why write javascript unit tests? <ul><li>Why write java tests? </li></ul><ul><li>Faster to test unit tests than to browse actual application </li></ul><ul><li>Can help find new bugs </li></ul><ul><li>Easy to add to part of build process, giving you another layer of testing </li></ul>
  5. 5. Code to be tested <ul><li>var validation = function () { </li></ul><ul><li>… </li></ul><ul><li>return { </li></ul><ul><li>validateAlphaNumeric: function (field) {..}, </li></ul><ul><li>validateUsername : function (field) { </li></ul><ul><li>$.ajax({…}); </li></ul><ul><li>} </li></ul><ul><li>} </li></ul><ul><li>} </li></ul>
  6. 6. JS Test Driver <ul><li>Project from google to automate javascript testing </li></ul><ul><li>Provides a javascript unit testing framework </li></ul><ul><li>Maven plug-in and eclipse plug-in </li></ul><ul><li>Uses real browsers </li></ul><ul><ul><li>However, I had problems with Chrome </li></ul></ul><ul><ul><li>Browsers weren’t always closed after </li></ul></ul><ul><li>No need to create fixture html – but you can specify html in each test </li></ul><ul><li>Server isn’t needed unless for AJAX </li></ul><ul><li>Has a QUnit adapter </li></ul><ul><li>Some flakiness, nothing I could reproduce reliably but I felt like it did weird stuff sometimes </li></ul><ul><li>http:// code.google.com/p/js -test-driver/ </li></ul>
  7. 7. Test Code <ul><li>TestCase(&quot;validateAlphaNumeric&quot;, { </li></ul><ul><li>&quot;test validateAlphaNumeric valid&quot; : function() { </li></ul><ul><li>/*:DOC input = <input type=&quot;text&quot; id=&quot;test_field&quot; value=&quot;aB1&quot; /> */ </li></ul><ul><li>var field = $(this.input), </li></ul><ul><li>isValid; </li></ul><ul><li>isValid = validation.validateAlphaNumeric(field); </li></ul><ul><li>assertEquals(&quot;aB1 should be valid&quot;, true, isValid); </li></ul><ul><li>}, </li></ul><ul><li>&quot;test validateAlphaNumeric invalid&quot; : function() { </li></ul><ul><li>/*:DOC input = <input type=&quot;text&quot; id=&quot;test_field&quot; value=&quot;!&quot; /> */ </li></ul><ul><li>var field = $(this.input), </li></ul><ul><li>isValid; </li></ul><ul><li>isValid = validation.validateAlphaNumeric(field); </li></ul><ul><li>assertEquals(&quot;! is not valid alphanumeric value&quot;, false, isValid); </li></ul><ul><li>} </li></ul><ul><li>}); </li></ul>
  8. 8. Sinon.JS <ul><li>A library for standalone test spies, stubs and mocks </li></ul><ul><li>Can also fake XHR (AJAX) and servers </li></ul><ul><li>http:// sinonjs.org / </li></ul>
  9. 9. Testing AJAX with SinonJS <ul><li>TestCase(&quot;validateUsername&quot;, sinon.testCase({ </li></ul><ul><ul><li>setUp : function() { </li></ul></ul><ul><ul><li>validation.reset(); </li></ul></ul><ul><ul><li>this.server = sinon.fakeServerWithClock.create(); </li></ul></ul><ul><ul><li>/*:DOC input = <input type=&quot;text&quot; id=&quot;test_field&quot; value=&quot;!&quot; /> */ </li></ul></ul><ul><ul><li>}, </li></ul></ul><ul><ul><li>tearDown: function() { </li></ul></ul><ul><ul><li>this.server.restore(); </li></ul></ul><ul><ul><li>}, </li></ul></ul><ul><ul><li>&quot;test validateUsername user name already used&quot; : function() { </li></ul></ul><ul><ul><ul><li>var field = $(this.input), isValid; </li></ul></ul></ul><ul><ul><ul><li>this.server.respondWith(createFakeResponse('error : username already used')); </li></ul></ul></ul><ul><ul><ul><li>isValid = callValidation(field, this.server); </li></ul></ul></ul><ul><ul><ul><li>assertEquals(&quot;should have got username already used error&quot;, isValid, false); </li></ul></ul></ul><ul><ul><li>} </li></ul></ul><ul><li>} </li></ul>
  10. 10. Testing AJAX with SinonJS <ul><li>function createFakeResponse(responseCode) { </li></ul><ul><li>return [ </li></ul><ul><li>200, </li></ul><ul><li>{ &quot;Content-Type&quot;: &quot;text/xml&quot; }, </li></ul><ul><li>'<?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?> <result>' + responseCode + '</result>' </li></ul><ul><li>]; </li></ul><ul><li>} </li></ul><ul><li>function callValidation(field, server) { </li></ul><ul><li>validation.validateUsername(field); </li></ul><ul><li>server.respond(); </li></ul><ul><li>return validation.validateAlphaNumeric(field); </li></ul><ul><li>} </li></ul>
  11. 11. JS Test Runner Demo <ul><li>Demo of eclipse plug-in </li></ul><ul><li>Demo of maven build </li></ul><ul><li>https://github.com/ryan-chambers/jstestdriver-sample-project </li></ul>
  12. 12. QUnit and Selenium <ul><li>QUnit is a javascript testing library originally written to test jQuery </li></ul><ul><li>Selenium tests using real browsers </li></ul><ul><ul><li>very slow </li></ul></ul><ul><ul><li>Typically only one browser is tested </li></ul></ul><ul><li>Meant for automated testing of page flows, not javascript unit testing </li></ul><ul><li>I wrote a sample test that only records whether all tests pass or not </li></ul><ul><ul><li>could possibly be updated to record actual error </li></ul></ul><ul><li>Requires creating an html page to host tests </li></ul><ul><li>https:// github.com/jquery/qunit </li></ul>
  13. 13. QUnit Test page <ul><li>Includes all required css and javascript </li></ul><ul><li>Adds elements to DOM that are required for test </li></ul><ul><li><input type= &quot;text&quot; id= &quot;test_field&quot; value= &quot;!&quot; /> </li></ul>
  14. 14. QUnit Tests - setup <ul><li>module(&quot;validation&quot;, { </li></ul><ul><li>setup : function () { </li></ul><ul><li>this.field = $('#test_field'); </li></ul><ul><li> validation.reset(); </li></ul><ul><li>}, </li></ul><ul><li>tearDown: function () { </li></ul><ul><li>this .xhr.restore(); </li></ul><ul><li>} </li></ul><ul><li>}); </li></ul>
  15. 15. QUnit Tests <ul><li>test(&quot;validateAlphaNumeric invalid&quot;, function () { </li></ul><ul><li>this.field.val('!'); </li></ul><ul><li>var isValid = validation.validateAlphaNumeric( </li></ul><ul><li>this.field); </li></ul><ul><li>equal(isValid, false , &quot;! Should </li></ul><ul><li>not be a valid alphanumeric </li></ul><ul><li>value&quot;); </li></ul><ul><li>}); </li></ul>
  16. 16. QUnit Tests with SinonJS <ul><li>function testFakeUserValidationWithResponse(responseCode, testHandler) { </li></ul><ul><li>var server = sinon.fakeServerWithClock.create(); </li></ul><ul><li>try { </li></ul><ul><li>server.respondWith([ </li></ul><ul><li>200, </li></ul><ul><li>{ &quot;Content-Type&quot;: &quot;text/xml&quot; }, </li></ul><ul><li>'<?xml version=&quot;1.0&quot; encoding=&quot;UTF- 8&quot;?><result>‘ </li></ul><ul><li>+ responseCode + '</ result >' </li></ul><ul><li> ]); </li></ul><ul><li> testHandler(server); </li></ul><ul><li>} finally { </li></ul><ul><li>server.restore(); </li></ul><ul><li>} </li></ul><ul><li>} </li></ul>
  17. 17. QUnit tests with SinonJS <ul><li>test(&quot;validateUsername user name already used&quot;, function ( </li></ul><ul><li>{ </li></ul><ul><li>var that = this; </li></ul><ul><li>testFakeUserValidationWithResponse(username_ already_used', function (server) { </li></ul><ul><li>validation.validateUsername(that.field); </li></ul><ul><li>server.respond(); </li></ul><ul><li>var isUsernameValid = validation.isUsernameValid(); </li></ul><ul><li>equal(isUsernameValid, false , &quot;should have got </li></ul><ul><li> username already used error&quot;); </li></ul><ul><li>}); </li></ul><ul><li>}); </li></ul>
  18. 18. Selenium <ul><li>public class ValidationIntegrationTest { </li></ul><ul><li>private WebDriver driver; </li></ul><ul><ul><li>@Before </li></ul></ul><ul><ul><li>public void setUp() throws Exception { </li></ul></ul><ul><ul><li>driver = new FirefoxDriver(); </li></ul></ul><ul><ul><li>} </li></ul></ul><ul><ul><li>@Test </li></ul></ul><ul><ul><li>public void testFormsIntegration() throws Exception { </li></ul></ul><ul><ul><ul><li>driver.get(&quot;http://localhost:8080/validation.html&quot;); </li></ul></ul></ul><ul><ul><ul><li>assertPageIsLoaded(); </li></ul></ul></ul><ul><ul><ul><li>List<WebElement> failedElements = driver.findElements(By. xpath (&quot;//span[@class='fail']&quot;)); </li></ul></ul></ul><ul><ul><ul><li>// could do more here to return failure messages </li></ul></ul></ul><ul><ul><ul><li>Assert. assertEquals (0, failedElements.size()); </li></ul></ul></ul><ul><ul><li>} </li></ul></ul><ul><ul><li>private void assertPageIsLoaded() { </li></ul></ul><ul><ul><li>driver.findElement(By. id (&quot;qunit-header&quot;)); </li></ul></ul><ul><ul><li>} </li></ul></ul><ul><ul><li>@After </li></ul></ul><ul><ul><li>public void tearDown() throws Exception { </li></ul></ul><ul><ul><li>driver.close(); </li></ul></ul><ul><ul><li>} </li></ul></ul><ul><li>} </li></ul>
  19. 19. QUnit demo <ul><li>View page in browser </li></ul><ul><li>Run unit test in eclipse w/ Jetty </li></ul><ul><li>https://github.com/ryan-chambers/qunit-selenium-sample-project </li></ul>
  20. 20. Jasmine Maven Plug-in <ul><li>Jasmine is a BDD javascript unit test framework </li></ul><ul><ul><li>You create a “spec” in a DSL that almost looks like English </li></ul></ul><ul><ul><li>BDD is very popular in Ruby on Rails </li></ul></ul><ul><li>https://github.com/pivotal/jasmine/wiki </li></ul><ul><li>Jasmine maven plug-in looks in certain directories for tests and their specs </li></ul><ul><ul><li>Can configure includes for libraries (eg. Jasmine/sinon plug-in) </li></ul></ul><ul><ul><li>Uses HTMLUnit for DOM </li></ul></ul><ul><li>https://github.com/searls/jasmine-maven-plugin </li></ul>
  21. 21. Jasmine Specs <ul><li>describe('validation', function () { </li></ul><ul><li>it('should detect valid alphanumeric sequences', function () { </li></ul><ul><li>var isValidAlphaNumeric = validation.isAlphaNumeric('aA1'); </li></ul><ul><li>expect(isValidAlphaNumeric).toEqual( true ); </li></ul><ul><li>}); </li></ul><ul><li>it('should detect invalid alphanumeric sequences', function () { </li></ul><ul><li>var isValidAlphaNumeric = validation.isAlphaNumeric('ab@google.com'); </li></ul><ul><li>expect(isValidAlphaNumeric).toEqual( false ); </li></ul><ul><li>}); </li></ul><ul><li>}); </li></ul>
  22. 22. Jasmine Maven Plug-in demo <ul><li>Run tests in browser </li></ul><ul><ul><li>mvn jasmine:bdd </li></ul></ul><ul><ul><li>http://localhost:8234 </li></ul></ul><ul><li>Run maven build </li></ul><ul><li>https:// github.com/ryan -chambers/maven-jasmine-sample-project </li></ul>
  23. 23. QUnit, PhantomJS and JS Test Runner <ul><li>PhantomJS is a command-line tool that embeds WebKit and can run javascript </li></ul><ul><ul><li>Very fast, since there is no browser </li></ul></ul><ul><li>http:// www.phantomjs.org / </li></ul><ul><li>JS Test Runner is a JUnit test runner that uses QUnit and Phantomjs for javascript </li></ul><ul><ul><li>Runnable from maven and eclipse </li></ul></ul><ul><li>http://js-testrunner.codehaus.org / </li></ul>
  24. 24. JS Test Runner <ul><li>@RunWith(JSTestSuiteRunner. class ) </li></ul><ul><li>@JSTestSuiteRunner.Include(value=&quot;validation.html&quot;) </li></ul><ul><li>public class ValidationJSTest { </li></ul><ul><li>} </li></ul>
  25. 25. QUnit, PhantomJS and JS Test Runner <ul><li>Run unit tests from Eclipse </li></ul><ul><li>Run build from maven </li></ul><ul><li>https://github.com/ryan-chambers/jstest-runner-sample-project </li></ul>
  26. 26. Questions?
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×