Creating a Fully Tested Web App

I’ve noticed that my standards for testing “frontend” code are much more lax than the standards I have for testing “backend” code. The attitude I often find myself making is that the backend stuff is more “important”. Anything that goes wrong in the frontend is just a superficial error. I might say something like, “Oh the response the server returned was actually correct, it just wasn’t displayed properly.” This is obviously incredibly stupid. After researching this I realized there are a lot of awesome technologies for testing web apps that I have yet to try. Here I present a proof of concept for a fully tested frontend: a minimal angular app that has unit tests of the client side javascript, and E2E tests to ensure the final rendered page is correct when shown in a browser.

The technology stack for this proof of concept is as follows:

Server: Express (Node.js web application framework)
App: Angular.js
Testing Environment: Karma.js
Testing Framework: Mocha.js
Assertion/Expectation Library: Chai.js
E2E Testing Framework: Protractor.js

First of all, there are a bunch of technologies floating out there to choose from, and many alternatives at each level. Most of the decisions I made here were the suggested tools for testing an angular app. Protractor.js is the preferred E2E framework for angular, and Karma.js is the preferred testing environment. Within Karma.js you have the option of choosing a few alternatives for writing the actual tests, they state support for Jasmine, Mocha, or QUnit. Mocha apparently offers more flexibility than Jasmine, but for my part this decision was pretty arbitrary. Part of this flexibility is choosing your own assertion library to use with Mocha, something which is “batteries included” with the Jasmine testing framework. For this I am using Chai. My server itself is written using Express, just because of its simplicity.

So lets start with the app itself, we have one controller:

And one view:

We will have a button that you click to make a number go up, like I said, a minimal static angular app. But how do we know that increment() will do what it implies? In steps karma. First we need to create karma config file, this will tell karma what javascripts to load and how exactly we want to test it. Our config looks like this:

Once we have this setup, we need to just create some tests in app/static/js/tests for karma to discover. We will have one test file which corresponds to our one controller, IndexController:

These tests are pretty exotic looking, so lets break them down:

describe is a function provided to us by the Mocha framework, it simply defines a block within which tests can be defined.

Next we see beforeEach(module('App'));, this is known as a hook in the Mocha framework. It will execute before every test defined inside of this block. The module is the angular.module function, which means we will instantiate our module before each test.

inject() comes to us from the angular mocks library, it will allow us to do the mock dependency injection necessary to instantiate a controller.

Finally after we are nested three deep in describe blocks, we have an actual live controller, which allows us access to attributes of the scope. Here we find our it() blocks, which are basically test cases in the Mocha framework.

Inside of this we have our expect calls, expect comes from chai, our assertion library, and will throw an error if our test conditions are not met.

This is all well and good, we expect that the scope will start off with theNumber being 0, and will increment up by one when increment() is called. But how can be certain that our webpage will actually display these changes correctly to the user? In come s Protractor. We start with our protractor configuration:

Protractor needs an actual browser to run, seeing as it must actually render the webpage. This config points it to a local selenium server (which we will spin up using the node module webdriver-manager, included with protractor), and then points it to a “spec” file, which contains our E2E tests:

This looks pretty similar to our Mocha tests. I’m not sure if it is using the same framework under the hood or just imitating it, but the consistency is nice. However, protractor lets us actually visit and inspect our webpage! We start with a call to browser() which will point to our local running express.js server. One the browser has loaded the page, we can use a jQuery like interface to find and inspect elements. We have carefully id tagged the elements of interest in our page, so that now we can easily find them and verify that our scope variable $scope.theNumber is indeed being displayed properly in the final rendered page. Hooray!

The code I have presented is available as a project seed on github: