Automated javascript unit testing

  • 9,678 views
Uploaded on

 

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
9,678
On Slideshare
0
From Embeds
0
Number of Embeds
0

Actions

Shares
Downloads
60
Comments
0
Likes
6

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Automated Javascript Unit Testing Ryan Chambers [email_address] Intelliware Development
  • 2. 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
  • 3. Testing Goals
    • Easy to develop tests in eclipse
    • Tests runnable as part of maven build
    • Fast
    • Cross-browser
  • 4. 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
  • 5. Code to be tested
    • var validation = function () {
    • return {
    • validateAlphaNumeric: function (field) {..},
    • validateUsername : function (field) {
    • $.ajax({…});
    • }
    • }
    • }
  • 6. 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/
  • 7. 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);
    • }
    • });
  • 8. Sinon.JS
    • A library for standalone test spies, stubs and mocks
    • Can also fake XHR (AJAX) and servers
    • http:// sinonjs.org /
  • 9. 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);
      • }
    • }
  • 10. 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);
    • }
  • 11. JS Test Runner Demo
    • Demo of eclipse plug-in
    • Demo of maven build
    • https://github.com/ryan-chambers/jstestdriver-sample-project
  • 12. 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
  • 13. 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; />
  • 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;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;);
    • });
  • 16. 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();
    • }
    • }
  • 17. 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;);
    • });
    • });
  • 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
    • View page in browser
    • Run unit test in eclipse w/ Jetty
    • https://github.com/ryan-chambers/qunit-selenium-sample-project
  • 20. 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
  • 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-in demo
    • 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 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 /
  • 24. JS Test Runner
    • @RunWith(JSTestSuiteRunner. class )
    • @JSTestSuiteRunner.Include(value=&quot;validation.html&quot;)
    • public class ValidationJSTest {
    • }
  • 25. QUnit, PhantomJS and JS Test Runner
    • Run unit tests from Eclipse
    • Run build from maven
    • https://github.com/ryan-chambers/jstest-runner-sample-project
  • 26. Questions?