Testable Javascript



David Aguilar
OC Dev
June 19, 2014


Who Am I?


David Aguilar

Application Architect
The Boeing Company

Desktop | Web | Mobile

Why Test?


  • Multiple Operating Systems
  • Multiple Versions of Operating Systems
  • Multiple Browsers
  • Multiple Versions of Browsers

Testing JavaScript is complicated.

Our best shot at taming this complexity is to take full control of what we actually do control: the code.

What is Testable Code?


  • Code that is easy to test :)
  • Less complex code
  • Fully commented
  • Loosely coupled

Testable JavaScript is your gateway to sanity!

Complexity


Complex = Bad; Simple = Good; 

Maintainable JavaScript is clear, consistent,
and standards-based.

Testable JavaScript is loosely coupled,
short, and isolatable.

The magic happens when your code is both
maintainable and testable.

JSLint


While JSLint does not measure complexity directly,
it does force you to know what your code is doing. 



Demo


Shoutout to: JavaScript: The Good Parts which provides detail on "good" vs. "bad" JavaScript syntactic constructs.

Reuse


The best way to reduce code size is to decrease
the amount of code you write.

Using a good JavaScript framework is an absolute
must in almost every circumstance.

  • jQuery
  • Closure
  • YUI
  • etc.

Unit Tests


Use a framework!

In the following examples, we will be using YUI Test.



There are other Unit Test Frameworks out there...

Your First Unit Test


Simple Function

 function sum(a, b) {
    return a + b;
}


Demo

Review


  • A new Y.Test.Case is created
  • Its given a name and set of test functions
  • Each function is run in turn with the assumption
    that one or more Y.Assert functions are called
    to actually test something
  • The test case is loaded into the local
    Y.Test.Runner and then all tests are executed

Mock Objects


Actual Production Code
function buyNowClicked(event) {
    hub.fire('addToShoppingCart', { item: event.target.id });
}

Y.one('#products').delegate('click', buyNowClicked, '.buy-now-button');
Test Code
 testAddToShoppingCart: function() {
    var hub = Y.Mock();
    Y.Mock.expect(hub,
         {
          method: "fire"
          , args: [ "addToShoppingCart" , Y.Mock.Value.String]
         }
    );
    Y.one('.buy-now-button').simulate('click');
    Y.Mock.verify(hub);

Review


  • This code tests the flow of a Buy Now button
    (an element that contains the
    buy-now-button CSS class)
  • When that button is clicked, the
    addToShoppingCart event is expected to be
    fired with a string parameter
  • The event hub is mocked out and the fire
    method is expected to be called with a
    single string parameter

Stubs


Actual Production Code
function addToShoppingCart(item) {
    if (item.inStock()) {
        this.cart.push(item);
        return item;
    } else {
        return null;
    }
}

STUBS


Test Code
 testAddOk: function() {
    var shoppingCart = new ShoppingCart()
    , item = { inStock: function() { return true; } }
    , back = shoppingCart.addToShoppingCart(item)
    ;

    Y.Assert.areSame(back, item, "Item not returned");
    Y.ArrayAssert.contains(item, "Item not pushed into cart!");
}
, testAddNok: function() {
    var shoppingCart = new ShoppingCart()
        , item = { inStock: function() { return false; } }
        , back = shoppingCart.addToShoppingCart(item)
    ;

    Y.Assert.isNull(back, "Item returned is not null");
    Y.ArrayAssert.isEmpty(shoppingCart.cart, "Cart not empty!");
}

Asynchronous Testing


Test Code
testAsync: function () {
    var test = this, myButton = Y.one('#button');
    myButton.on('click', function() {
         this.resume(function() {
              Y.Assert.isTrue(true, 'You sunk my battleship!');
         });
    }
    myButton.simulate('click');
    this.wait(2000);
}

Great for code that has alot of CSS manipulation in response to events.

Running Tests


How do we automate all these Unit Tests?

  • PhantomJS - headless WebKit browser that
    can be accessed programmatically
  • Selenium - web browser automation tool
    (also works for mobile)



Debugging


If you don't by now, get familiar with your browsers debugging tools.

  • Chrome - Developer Tools
  • Firefox - Firebug
  • Safari - Web Inspector
  • Internet Explorer (8+) - F12 Developer Tools

Also, know what your user-base is using!

Debugging



Chrome Developer Tools


Demo

Mobile Debugging



Safari Web Inspector

Demo

Adobe Edge Inspect


  1. Edge Inspect CC
  2. Edge Inspect Chrome Plugin
  3. Device(s)






Demo



Reference


  • Testable JavaScript by Mark Ethan Trostler (O’Reilly).
    Copyright 2013 ZZO Associates, 978-1-449-32339-4.

  • Javascript: The Good Parts by Douglas Crockford (O'Reilly).
    Copyright 2008 O'Reilly Media, 978-0596517748.

Thank You!




David Aguilar
@davidraguilar

Testable Javascript

By dcfusion

Testable Javascript

  • 1,299