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.
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
- Edge Inspect CC
- Edge Inspect Chrome Plugin
- 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