One of the first questions I always hear when starting with a new client is “How can I build unit tests for my application?”
It’s obvious that many people understand the benefits of unit tests—developers want to minimize the number of bugs in their code and managers want to reduce the amount of time required to test an application before release. Although the concept of unit testing has existed for years, software teams are only now beginning to explore building tests for their Rich Internet Applications (RIAs).
In my experience, it’s obvious that most people don’t fully understand what it means to build unit tests for RIAs. Considering there are few tutorials explaining how to accomplish this, I wanted to share a recent experience with the community in hopes that it will stimulate ideas and discussion.
Keep an open mind as you follow along with this post and think about how these examples might fit into your own processes. This implementation is one of any number of possible solutions, and I don’t attempt to solve every problem. That being said, implementing unit tests into your project will produce cleaner, more stable code and will reinforce coding standards throughout your organization.
I. Unit Testing Web Applications: An Overview
When building unit tests for RIAs, it’s important to remember that the user interface (the “presentation layer”) is very different from the supporting layers of the application.
Because the presentation layer has multiple responsibilities, it is important to separate unit tests into the following three areas:
- Syntax Checks – Syntax checks are not exactly unit tests because there is no logic being tested. Instead we analyze our code for syntactical errors – errors that may or may not be caught before application execution.
- Unit Tests – True to its contemporary meaning within software development, unit tests are a series of objective logic tests. Unit tests attempt to isolate small pieces of our code: given specific inputs, unit tests expect specific outputs. In this manner unit tests are essentially mathematical proofs (remember those from high school?) that confirm what our business logic is supposed to do.
- UI Tests (aka Integration Tests) – UI Tests are not the same as unit tests. UI Tests attempt to subjectively verify that elements on the screen behave (and/or look) as expected when a user performs a given action. There is no math or logic involved: the tests render the environment as a whole (containing all runtime dependencies) and wait to verify that the DOM has changed in a desired way. You can think of these tests as a robot manually testing the application.
I do not attempt to solve the problem of UI Tests in this post, but there are helpful links are included at the end if you’re interested.
II. A Sample Application
The key to implementing unit tests is to automate the process – if the tests aren’t run every time the code changes (or at some regular interval), the tests become ineffective and useless.
I have created a sample project that uses shell scripts to run each individual part (syntax checks and unit tests). These scripts return status codes upon success and failure.
The specific process to integrate these automated tests may be quite different at every company. The shell scripts might provide automation by:
- being integrated into a build process (e.g. via Ant)
- being integrated into source control hooks (e.g. a Git pre-commit hook on your local machine)
The sample project (and the concepts explained below) assume a certain degree of knowledge on the following tools:
- Sencha SDK Tools (v2.0.0b3) – a suite of automation tools assisting with application creation, development and deployment
The shell scripts in the sample project were targeted towards Mac OSX/Linux users. However, Windows batch (.bat) files or Ant scripts can easily accomplish the same thing and should be easy to create.
IV. Syntax Checks
Taking a look in the sample project under /tests/, you should see a shell script named “run_lint.sh”. This script launches the PhantomJS environment and initializes PhantomLint for us (JSLint-Runner.js). Given its configuration options, PhantomLint then dives into the filesystem to test our code against JSLint. Any errors are then output to a text file.
If you run the shell script, you should notice a single error in our application code: