KEMBAR78
Automated javascript unit testing | PPT
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(&quot;validateAlphaNumeric&quot;, { &quot;test validateAlphaNumeric valid&quot; : 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?

Automated javascript unit testing

  • 1.
    Automated Javascript UnitTesting Ryan Chambers [email_address] Intelliware Development
  • 2.
    Outline Why shouldI 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
  • 3.
    Testing Goals Easyto develop tests in eclipse Tests runnable as part of maven build Fast Cross-browser
  • 4.
    Why write javascriptunit 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
  • 5.
    Code to betested var validation = function () { … return { validateAlphaNumeric: function (field) {..}, validateUsername : function (field) { $.ajax({…}); } } }
  • 6.
    JS Test DriverProject 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/
  • 7.
    Test Code TestCase(&quot;validateAlphaNumeric&quot;,{ &quot;test validateAlphaNumeric valid&quot; : 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); } });
  • 8.
    Sinon.JS A libraryfor standalone test spies, stubs and mocks Can also fake XHR (AJAX) and servers http:// sinonjs.org /
  • 9.
    Testing AJAX withSinonJS 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); } }
  • 10.
    Testing AJAX withSinonJS 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); }
  • 11.
    JS Test RunnerDemo Demo of eclipse plug-in Demo of maven build https://github.com/ryan-chambers/jstestdriver-sample-project
  • 12.
    QUnit and SeleniumQUnit 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
  • 13.
    QUnit Test pageIncludes 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; />
  • 14.
    QUnit Tests -setup module(&quot;validation&quot;, { setup : function () { this.field = $('#test_field'); validation.reset(); }, tearDown: function () { this .xhr.restore(); } });
  • 15.
    QUnit Tests test(&quot;validateAlphaNumericinvalid&quot;, function () { this.field.val('!'); var isValid = validation.validateAlphaNumeric( this.field); equal(isValid, false , &quot;! Should not be a valid alphanumeric value&quot;); });
  • 16.
    QUnit Tests withSinonJS 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(); } }
  • 17.
    QUnit tests withSinonJS 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;); }); });
  • 18.
    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(); } }
  • 19.
    QUnit demo Viewpage in browser Run unit test in eclipse w/ Jetty https://github.com/ryan-chambers/qunit-selenium-sample-project
  • 20.
    Jasmine Maven Plug-inJasmine 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
  • 21.
    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 ); }); });
  • 22.
    Jasmine Maven Plug-indemo Run tests in browser mvn jasmine:bdd http://localhost:8234 Run maven build https:// github.com/ryan -chambers/maven-jasmine-sample-project
  • 23.
    QUnit, PhantomJS andJS 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 /
  • 24.
    JS Test Runner@RunWith(JSTestSuiteRunner. class ) @JSTestSuiteRunner.Include(value=&quot;validation.html&quot;) public class ValidationJSTest { }
  • 25.
    QUnit, PhantomJS andJS Test Runner Run unit tests from Eclipse Run build from maven https://github.com/ryan-chambers/jstest-runner-sample-project
  • 26.