Monday, February 6, 2012

Class-less javascript


Intro

It seems that every javascript framework of a certain size is compelled to implement some kind of pseudo-classical type system. I am now fairly convinced that there is no good reason for doing so. I’d like to describe an alternative approach to dealing with types in javascript.


This approach comes from a recent project where my team were building a pure-javascript single-page web application. This wasn’t a huge codebase, but due to the single-page nature of the app it did have a reasonable amount of non-presentation logic which was implemented client-side in javascript. We needed a type system but we knew we didn’t want to try and force a classical-OO system onto javascript. The patterns we evolved gave us just enough structure while still allowing us to take advantage of the highly flexible and dynamic nature of javascript.


In this post I’ll be summarizing the major parts of the lightweight, class-less type system we created. Before that I’ll start with a brief tour of javascript, covering language concepts which are relevant to our approach. If there is sufficient interest in this topic I may write this up in more detail here over a series of posts.


A quick tour of Javascript


Prototypical, not Classical

Javascript is not a classical Object-Oriented language. Over the years many have tried to force it into that mold, but it just doesn’t fit. In javascript typing is achieved through the use of prototypes, not classes.


In languages like Ruby or Java you have Classes and Objects. An Object is always the instance of a specific Class. You generally define an object’s behaviour by specifying that behaviour in the object’s class (for the sake of clarity I’m glossing over things like ruby’s eigenclass). On the other hand in javascript an object’s type is not determined by its class, but is instead based on the object’s prototype. Unlike classes, a prototype has no special qualities. Any object can act as the prototype for another object. A prototype is not distinct from other objects, nor does it have a special type.


In a classical OO language an object derives behaviour and state-shape (i.e. member variables) from its class, and also from superclasses of its class. In javascript, an object derives behaviour from its prototype and also from its prototype’s prototype, and so on up the prototype chain.


Objects are just a bag of key-value pairs

Javascript objects are in essence just a dictionary of key-value pairs called properties (plus a prototype as described above). Public object state is added directly to the object as a property, and object ‘methods’ are simply a function which has been added directly to the object (or its prototypes) as a property.


Closures as an alternate source of per-instance state

Storing state directly in an object via its properties would mean that that state is publicly accessible in a similar fashion to a public instance variable in an OO language. This has the same drawbacks as in other languages (uncontrolled access, unclear public interfaces, etc.). To avoid this pitfall a common idiom used in javascript to control access to state is to instead store that state outside of the object itself, but rather as local variables of the function which created that object. Due to the scoping rules of javascript those local variables are closed over by the object, and are thus available for access and modification.





Note that the duck instance we create is not storing its name anywhere inside the object. Instead the name argument passed to the createDuck function has been closed over, and is accessible to that duck instance. Also note that the value of name is therefore private. In fact it is private in a very strong sense. It is impossible for any client of the duck instance to see or modify the value of that name variable. No tricks of reflection or runtime object manipulation can get around this. Interesting sandboxing systems such as Caja have been built up around this property of javascript.


A lightweight type system for Javascript


Constructor functions, not classes

In a typical OO system you would define the types in your system using classes such as Duck, Pond, Food, etc. The orthodox approach in javascript would be to define types using prototypes. In our approach we do neither. We have no classes or prototypes, just constructor functions. Each type in the system has one or more constructor functions which create instance of that type. So we would have createDuck(…), createPond(…), createFood(…).


The closure code sample above shows the general form these constructor functions take. The equivalent of methods and member variables are defined inside the constructor function and at the tail end of the function an object with references to the methods is created and returned.


State via closure

As mentioned earlier, storing state directly in object properties is analogous to having public instance variables. There are very few cases where this is a good idea. Instead our objects maintain state via closed-over local variables declared in the object’s constructor functions. In this way object state is private and encapsulated but still available for manipulation by the object’s functions, because they are declared in the same constructor function. Access to state is exposed in the public interface of a type instance via these functions which are added to the returned object, becomding ‘methods’ on that instance.


Mixins for shared public behaviour

In javascript public ‘methods’ are just functions added to an object as a property. This means you can easily mix in new public behaviour by just merging the contents of the a mixin object with the instance itself. For example:



Here we have a shouter mixin and a createShoutyDuck constructor function which uses that mixin to construct a new type of duck which can shout. The constructor achieves this by using the methods defined in shouter to extend the duck type that is defined by the createDuck constructor function. We often use this pattern as an alternative to implementation inheritance. Instead of a base class which provided standard behaviour and subclasses which layer on additional behaviour we instead would have a base mixin which provides standard behaviour and constructor functions which define types by mixing together that standard base behaviour with additional type-specific behaviour. It’s also interesting to note that as well as using mixins to extend a type via a constructor function it is also possible to extend specific instances of a type with mixed in functionality on an ad-hoc basis. This allows interesting dynamic patterns such as mixing in ‘admin’ methods to a specific instance of a User type once they have been authorized as an admin via a service call.


Namespacing

We follow the standard practice in large javascript codebases of namespacing using the module pattern. Coupled with our other practices, this means that a module will generally only expose a small number of constructor functions to other parts of the system. Inside a namespace we may have quite a few types (and thus constructor functions), but across module boundaries only a few types are shared, and thus only a few constructor functions exposed. This is a natural outcome of following the time-honored practice of organizing modules with low coupling and high cohesion in mind. Global variables are avoided at all costs, and pseudo-global variables (i.e. raw variables tacked on to a top-level namespace) are considered a design smell.


Dependencies

Dependencies are wired together in an initial boot function. Because this function’s role is to connect large modules together it has a side-effect of documenting in a relatively declarative, high-level way how the various parts of the system depend on each other.


Dependencies are generally hooked in by providing constructor functions as parameters to other constructor functions. As well as directly passing constructor functions, it’s also quite common that partially-specified constructor functions are used to encapsulate lower-level or cross-functional dependencies. Here’s another contrived example:




This example shows two distinct applications of currying. First, we have exposed a curried createDuck function to the outside world, with the logger dependency hidden. We also used a curried createLogger function called duckLogger to pass to the createDuck function. Again this was to remove cross-functional implementation details (about logging in this case) which the createDuck constructor should not be aware of or care about.


There is a strong similarity between our use of partially applied functions and the parameterized Factory classes you see quite often in statically typed OO code (particularly Java).


A notable advantage of this dependency injection approach is that modules can easily be tested in isolation by injecting test doubles in place of real dependencies.


Outcomes


Composition over Inheritance

A slightly unfortunate side-effect of capturing our instance state in closures is that it is hard to expose that state to mixins and sub-classes, as the state is only available via lexical scoping and is not available via the this keyword. Another way of putting this is that there is no equivalent of the ‘protected’ scope found in a language like C++ or Java. This leads to a favoring of composition over inheritance/mixin when it comes to sharing common behaviour between types. Instead of mixing in behaviour that requires access to private state we would wrap that behaviour in a helper object. That helper object would be available to types which need it via their constructor function. Instances of those types would then call out to that helper object as needed, passing in the private state needed by the helper to provide its functionality. Sort of a ‘tell-don’t-ask’ approach to using shared behaviour.


No prototypes, no new, less this

By following this approach to creating types we’ve found no need for the prototypical type system built into javascript. Our code does not use the new operator at all, except when interacting with libraries or frameworks which require the use of new to instantiate objects.


The lack of new also means usage of the this keyword becomes less frequent. References from a method’s implementation to member variables or to other methods in a type are mostly achieved via lexical scoping. this is only really needed when writing mixins which achieve their work by calling hook methods implemented in the instances they are mixed into - see the shouty duck sample above for an example of that.


Conclusion


I have been honestly rather surprised at how well this class-less approach has worked. I would certainly use it (and refine it) in future javascript projects.


I’d love to hear feedback on what I’ve outlined here. If there is interest I may write some follow-up posts diving into more detail on some of the aspects I’ve touched on here.

Friday, September 2, 2011

Testing Mobile Web Apps With WebDriver

Intro

We’ve been building mobile web apps using JQuery Mobile with the main target being webkit-based mobile browsers - Android and iPhone, basically. We’re big fans of functional testing, so we spent some time figuring out how to get a good testing infrastructure set up for mobile app development. That’s what I’ll be sharing here.


The approach


Our team members have a lot of experience using Cucumber to write automated acceptance tests, and we’re big fans. In previous projects we were building native iOS apps and testing them using Cucumber and Frank. We wanted to bring over some of the testing infrastructure we already had set up, so we decided on a similar approach. We still use Cucumber to drive tests in the iOS simulator, but instead of talking to a native app using Frank we are talking to our mobile web app via Selenium 2’s remote WebDriver protocol. In order to do this we run a special iOS app provided as part of Selenium 2 called iWebDriver which hosts an embedded UIWebView and listens for WebDriver commands, in much the same way as a Frankified native app listens for Frankly commands. We launch the iWebDriver app using the same SimLauncher gem which we’ve previously used to launch our native app for pre-commit and CI testing. To make our lives easier we use Capybara, which provides a nice ruby DSL for driving web apps and some useful cucumber step definitions out of the box. We configure Capybara to use the selenium-webdriver gem to drive the iWebDriver-hosted web app via the WebDriver remote protocol.


Selenium 2 == WebDriver

Note that when I talk about Selenium here, I am not referring to the Selenium 1.0 system (Selenium RC, Selenium IDE and friends). We are using Selenium 2.0, which is essentially the WebDriver system plus some Selenium backwards compatibility stuff which isn’t used in this setup. We don’t run any kind of Selenium server, we simply run iWebDriver in the iOS simulator. iWebDriver exposes the WebDriver remote API, and our cucumber tests drive our mobile app directly within iWebDriver using that API.


WebDriver on mobile is still bleeding edge

On the whole we have been happy using WebDriver and the iOS simulator to drive our functional tests. However, the WebDriver infrastructure for mobile platforms does feel a little rough around the edges. We have rare cases where our CI test run will fail, apparently due to iWebDriver crashing. When we were first getting our app under test we saw what appeared to be an iWebDriver bug where it was overwriting the global _ variable that underscore.js uses. We worked around that by using underscore.js in no-conflict mode. We also had to add a small but hacky monkey-patch to the selenium-webdriver gem to work around a bug in the way CocoaHTTPServer (the embedded HTTP server that iWebDriver uses) handled a POST with an empty body. That bug has been fixed in more recent releases of CocoaHTTPServer, but frustratingly we got no response when we reported the issue and suggested an upgrade of the dependency to resolve the issue. UPDATE: Jari Bakken notes in the comments that a similar workaround to our monkey-patch has now been added to the selenium-webdriver gem. We also found that iWebDriver locks up when showing a javascript alert. We worked around this by injecting a stub version of window.alert() in our web page at the start of each test. This worked, but is obviously less than ideal.


We briefly experimented with using the Android WebDriver client, but it lacked support for CSS-based selectors at the time. That may have changed since. If you are just using Capybara this is not an issue since Capybara uses XPath under the hood. However we quickly found that our use of JQuery Mobile meant we needed to write a fair amount of custom selectors, and our automation engineers had a preference for CSS. Ideally we would have run our test suite against both the iOS simulator and the Android emulator, but this lack of CSS support led to us deciding to just test on iOS. Given that both platforms are webkit-based this was an acceptable tradeoff.


The last drawback worth mentioning around using the iOS simulator is that it can only be run under OS X, and it doesn’t seem possible to run multiple instances of the simulator at once. This means that parallelizing your tests will involve running multiple OS X host machines, either physical boxes (we have used mac minis successfully) or virtual machines.


Recommendations

All in all I would still recommend a testing approach similar to what I’ve outlined. The extra safety-net that our suite of functional tests provided was just as valuable as in a non-mobile project. While they are not totally polished, iWebDriver and Cucumber are the best way I know of currently to build that safety net.


One thing we didn’t do which I would recommend is to also have your test suite execute against a desktop webkit-based browser, using ChromeDriver for example. Tests will run a lot quicker on that platform, giving you faster feedback. You will likely need to make minor modifications to the way your tests are written, but if you’re running tests in ChromeDriver from day one then you should be able to tackle any small issues as and when they arise. That said, I would absolutely make sure you are also running your full test suite against at least one mobile platform as frequently as you can - there will be issues in mobile webkit browsers that aren’t apparent on a desktop browser.

Saturday, July 2, 2011

Javascript Promises

One of the interesting aspects of Javascript development is its asynchronous, event-driven nature. Any operation which will take a significant amount of time (e.g. a network request) is non-blocking. You don’t call a function and block until the operation completes. Instead functions are non-blocking - they return before the operation is complete. To obtain the result of the operation you provide callbacks which are subsequently invoked once the operation completes, allowing you to move on to the next stage in your computation. This is a very powerful, efficient model that avoids the need for things like explicit threading and all the associated synchronization problems. However, it does make it a bit harder to implement a set of operations that need to happen one after another in sequential series. Instead of writing:

 
var response = makeNetworkRequest(),
processedData = processResponse(response);
writeToDB( processedData );

you end up writing:

 
makeNetworkRequest( function(response){
  var processedData = processResponse(response);
  writeToDB( processedData, function(){
    // OK, I'm done now, next action goes here.
  });
});

This is the start of what is sometimes referred to as a callback pyramid - callbacks invoking subsequent operations passing in callbacks which are invoking subsequent operations, and on and on. This is particularly common in node.js code, because most server-side applications involve a fair amount of IO-bound operations (service calls, DB calls, file system calls) which are all implemented asynchronously in node. Because this is a common issue there have been a rash of libraries to help mitigate it. See for example “How to Survive Asynchronous Programming in JavaScript” on InfoQ.

One approach to help cope with these issues in asynchronous systems is the Promise pattern. This has been floating around the comp-sci realm since the 70s, but has recently found popularity in the javascript community as it starts to build larger async systems. The basic idea is quite simple. When you call a function which performs some long-running operation instead of that function blocking and then eventually returning with the result of the operation it will instead return immediately, but rather than passing back the result of the operation (which isn’t available yet) it passes back a promise. This promise is a sort of proxy, representing the future result of the operation. You would then register a callback on the promise, which will be executed by the promise once the operation does complete and the result is available. Here’s the same example as I used before, implemented in a promise style:

 
var networkRequestPromise = makeNetworkRequest();
networkRequestPromise.then( function(response){
  var processedData = processResponse(response),
  dbPromise = writeToDB(processedData);
  dbPromise.then( function(){
    // OK, I'm done now, next action goes here.
  });
});

I created local promise variable here to show explicitly what’s happening. Usually you’d inline those, giving you:

 
makeNetworkRequest().then( function(response){
  var processedData = processResponse(response); 
  writeToDB(processedData).then( function(){
    // OK, I'm done now, next action goes here.
  });
});

For a simple example like this there’s really not much advantage over passing the callbacks as arguments as in the previous example. The advantages come once you need to compose asynchronous operations in complex ways. As an example, you can imagine a server-side app wanting to do something like: “make this network request and read this value from the DB in parallel, then perform some computation, then write to the DB and write a log to disk in parallel, then write a network response”. The beauty of a promise is that it is an encapsulated representation of an async operation in process which can be returned from functions, passed to functions, stored in a queue, etc. That’s what allows the composition of async operations in a more abstract way, leading to a much more manageable codebase.

Sunday, May 8, 2011

retroactive quality metrics with git

The Background

For a recent project retrospective we wanted to chart some metrics over the course of the entire project. Things like number of unit tests, test coverage, how long builds took to run, number of failing tests, etc. Taken in isolation these metrics aren't incredibly exciting, but when you plot them over time and hold that against other metrics like team morale, story point velocity, open defects, etc then often some interesting correlations can emerge.

The Challenge

So, we wanted metrics for internal quality, but we actually hadn't done the best job at collecting those metrics, particularly at the start of the project. So under pressure to get ready for our project retro we decided that we'd have to pass on graphing the internal quality metrics.

After the retrospective - which was a very valuable exercise regardless - I decided to figure out a way to capture this kind of data retroactively. I reasoned that if we had a script which generated a metric for the codebase at an instance in time then we can easily leverage The Awesome Power Of Git™ to collect that same metric over an entire set of commits.

Find someone else who's solved 80% of your problem

I came across a script in Gary Bernhardt's dotfiles repo on github called run-command-on-git-revisions. Sounds promising, doesn't it? This script will take a given range of git commits and run whatever command you provide on each commit in the range one by one. Just what I needed.

Solve the remaining 20%

I just needed a few additional tweaks. First I created a little 5 line ruby script which ran some test coverage metrics on our codebase, outputting a single line of comma-separated data. Then I created a modified version of Gary's script. The modified script only outputted raw CSV data, and tacked on the timestamp of each git commit as it processed it. Once that was done all I had to do was kick off the script with the appropriate range of commits, asking it to run my metric reporter script on each commit. I took the output and pulled it into graphing software and now have a pretty graph of how our test code has trended over time.

Sunday, May 1, 2011

Inspect the state of your running iOS app's UI with Symbiote

What's Symbiote?

Frank comes with a useful little tool called Symbiote. It's a little web app which is embedded inside your native iOS application. Its purpose is to let you inspect the current state of your app's UI, and to test the UIQuery selectors which Frank uses to help it automate your app. Essentially Symbiote is Firebug for your native iOS app.

Recently I've added some improvements to Symbiote, adding some new features and making it easier to use. This screencast demonstrates most of the new-and-improved Symbiote.

Main features

View hierarchy

Symbiote provides you with a tree describing the current state of the view hierarchy of your running app. This gives you an overview of the general structure of your app's UI, and also helps you write UIQuery selectors which drill down from high level UI features to individual UI elements. For example, you might want to find a specific UITableView, and from there drill down to a specific row within that table view.

View properties

After selecting a specific view in the view hierarchy you can see details of that view in a properties tab. Inside this tab is a table describing all the properties exposed by the specific view.

UI Snapshot, with view locator

The View Locator tab shows a snapshot of the current app UI. As you mouse over views in the view hierarchy that view will be highlighted in the view locator, making it easy to visualize which parts of the view tree map to which parts of the app's UI.

Selector testing

Frank uses UIQuery selectors during testing to select a specific view or set of views. This is very similar to how Selenium uses XPath or CSS selectors. In order to test these, Symbiote allows you to provide free-form UIQuery selectors and then have Frank flash any matching views in your app's live UI. This makes it a lot easier to test selectors when writing your automated tests.

Accessible elements

Frank makes use of accessibility labels to make it easier for it to find elements in the UI. To that end, Symbiote provides a list of all the views in your current UI which have accessibility labels. You can click on these elements and see the corresponding UI element flash in your app's running UI, using the same mechanism as the free-from selector input field.

Cool, where do I get it?

That's easy. Just get your app Frankified, and you're good to go!

Gracias!

We wouldn't have what we have today without the original UI cleanup of Symbiote by Cory Smith, and the UX and CSS help of Mike Long.

Tuesday, April 19, 2011

Tutorial screencast on Frankifying your app

I maintain Frank, a tool which lets you write automated acceptance tests for your iOS app using Cucumber. I've been trying to reduce the hurdles in getting started with Frank. My latest attempt is to record a tutorial screencast showing how to take your existing app and 'Frankify' it.

'Frankifying' an app is the process of adding a separate Frank target to your app which has the Frank server embedded into it, allowing it to respond to automation commands. It can seem like a bit of an intimidating process at first glance, but it's actually very simple. Hopefully running through the whole process in a 7 minute screencast demonstrates that.

Derek Longmuir has also contributed a nice in-depth tutorial writeup (which I was following along with when I recorded the screencast).

Tuesday, January 4, 2011

Working with Indirect Input and Output in Unit Tests

Testing how a unit of code interacts with its environment

When testing a unit of code you need to both observe how the unit of code is interacting with the outside world and also control how the world interacts with it.

In a particuarly simple example, you might want to check that when an adder function is given a 2 and a 4 then it returns a 6. In this case you’re controlling what the System Under Test (SUT) pulls in from its environment (the 2 and the 4) and also observing what it pushes out (the 6). In a more sophisticated example you might be testing a method which talks to a remote service, verifying that if it receives an error code when trying to read from the network then it logs the appropriate error message to a logger. Note that we’re still doing essentially the same thing here - controlling what the SUT pulls in from the environment (an error code in this case) and observing what it pushes out (a call to a logger in this case).

These two examples both illustrate the same fundamental practice of controlling input and observing output, but they are dealing with different kinds of input and output. In the first example of the adder function we are controlling the Direct Input provided to the SUT, and observing the Direct Output. In the second example we are controlling Indirect Input and observing Indirect Output (these terms are courtesy of the quite great XUnit Test Patterns book).

Four categories of inputs and outputs

As you can see, direct input and output is so called because it is provided directly to the SUT by the unit test. On the other hand, Indirect Input and Output can only be controlled and observed indirectly, via the SUT’s dependencies (aka Depended Upon Components). In one of the previous examples we were testing some code which needed to talk to a remote service. In that case the SUT would have had a dependency on some sort of lower level network service. We used this dependency to inject Indirect Input in the form of an error code being returned when the network service was called. Our SUT also had a dependency on some sort of logging service. We used that dependency to observe Indirect Output by checking that a logging method was called with the logging information we expect in the circumstances we simulated using the Indirect Input of an error coming back from the network service.

How do we manage indirect input and output?

We control indirect input and measure indirect output within our Unit Tests by using Test Doubles. This term encompasses the test-specific doohickeys commonly referred to as Mocks and Stubs, as well as the more esoteric variants such as Spies, Dummies, Fakes, etc.

In my personal opinion the vocabulary for these things is pretty confusing, and the definitions do not appear to be universally agreed upon and consistent. Also, I don’t often find myself too concerned with the implementation-specific differences which for some definitions serve to distinguish between e.g. a Stub vs a Mock. To me a much more important distinction is in what role a specific Test Double is playing in the test at hand. Is it helping to inject Indirect Input, or is it helping to observe Indirect Output? Or is it simply there to replace a required dependency for which we don’t want to use a real implementation? In an ill-advised mixing of terminology, I categorize these roles as Mocking, Stubbing, or Faking. I know this aligns quite poorly with other definitions for these terms, but they’re the best I have for now.

Test Double Roles

Stubbing

This refers to using a Test Double to control your SUT by providing specific Indirect Input. For example, you might supply your SUT with a testing-specific implementation of a Car repository which you have pre-configured to return a specific Car instance. This Car instance would be the indirect input which you are providing to your SUT. Another classic example would be injecting a fake Clock into your SUT so that you can test how it behaves at 1 second before midnight, or on February 29, or on December 21 2012.

Mocking

This refers to using a Test Double to observe some piece of Indirect Output produced by your SUT. Perhaps you’re creating a system that lets people tweet messages to the Jumbotron at a baseball game, and you need to make sure that you filter the tweets for naughty words. You could supply your SUT with a mock implementation of a RudeWordFilter class, and check that its filtering methods are being called correctly.

Faking

A Faking Test Double is one which is just being used to satisfy the SUT’s dependencies, and which is not being used to provide Indirect Input or to observe Indirect Output. Maybe the method you’re testing writes entries to a logger as it goes about its business. Your current test doesn’t care about this behavior, so you provide a Null Object implementation of the Logger to the SUT. This Null logger will simply ignore any logging methods which are called on it. Note that I emphasized that the current test wasn’t interested in how the SUT uses the logger. Other tests likely would be, and in those tests the Test Double which provides the Logger dependency would likely play a Mocking role rather than a Faking role.

Test Double Roles vs Test Double Implementation

It’s important to note here that the way in which these Test Doubles are implemented is orthogonal to the role they are playing. You can use a ‘mocking framework’ (e.g. Mockito, JMock, Typemock, EasyMock) both to supply Indirect Input and to observe Indirect Output. On the other hand you could just as well use hand-written classes (sometimes referred to as stubs) to achieve both these goals. This orthogonality between the technique you’re using to create your Test Doubles and the role a Test Double is playing is an important but subtle point, and is part of why I’m really not happy with the confusing terminology I have been using.

Acknowledgements

Lots of the ideas in this post are inspired by the patterns in the wonderful, encyclopedic XUnit Test Patterns book. It’s not exactly a 5 minute read, but nevertheless I highly recommend it. Most of the patterns in the book are also covered in very high-level overview form on the accompanying website, xunitpatterns.com.

I think my categorization of the Mocking, Stubbing and Faking roles lines up pretty closely with what Roy Osherove describes in his book, The art of unit testing, but I haven’t read the book so I can’t say that with any confidence.