Continous Integration, Grunt, Javascript, Tests, Xvfb

Running UI tests on real browsers in continuous integration using X virtual framebuffer (trough a task-runner)

Many times when projects run UI tests as part of CI (continuous integration) they rely on PhantomJS, a great headless browser. Unfortunately, using PhantomJS has some drawbacks:

  1. You really don’t cover quirks happening from browser to browser (working on chrome, not on FF, working on FF, not working on IE), so you might actually ship a buggy screen to production
  2. Debugging is hard. Although PhantomJS runs on top of WebKit, it has it own quirks, so you might get failing tests while all of your browsers show that everything’s OK. Debugging something you can’t see is troublesome.

UI tests with real browsers

So you’re not completely satisfied with PhantomJS and you want to run your UI tests on real browsers, which is a good idea that have a little difficulty (or not): you want your UI tests to run as part of CI, but most of CI servers don’t have displays.

Enter Xvfb (X virtual framebuffer). From Wikipedia: Xvfb is a display server implementing the X11 display server protocol. In contrast to other display servers, Xvfb performs all graphical operations in memory without showing any screen output. From the point of view of the client, it acts exactly like any other X display server, serving requests and sending events and errors as appropriate. However, no output is shown. This virtual server does not require the computer it is running on to have a screen or any input device. Only a network layer is necessary.

So basically what you’ll need to do is:

  1. Start Xvfb
  2. Run your tests
  3. Kill Xvfb

Running Xvfb trough a task runner

In this example we’ll use Grunt to run Xvfb as one of the tasks, but this is also possible with Gulp (I’m not sure about the others).
First, we’ll install the required packages, make sure you’re not forgetting to –save-dev since we want to update our package.json with the new dependency for development.

npm install --save-dev grunt-env
npm install --save-dev grunt-shell-spawn

Next we’ll setup grunt tasks for Xvfb:

        shell: {
            xvfb: {
                command: 'Xvfb :99 -ac -screen 0 1600x1200x24',
                options: {
                    async: true
        env: {
            xvfb: {
                DISPLAY: ':99'

Now we’ll setup the UI test task, for the example we’ll use protractor but it can be any other library.

protractor: {
            options: {
                keepAlive: false,
                configFile: "protractor.conf.js"
            run: {}

In protractor.conf.js we should create configuration to run UI tests on the required browsers (I assume you have already the proper setup for this, since it’s not in the scope of this post).

Now we got:

  1. Grunt test task configuration
  2. Protractor configuration which will run the tests on all the required browsers
  3. Grunt Xvfb tasks configuration

Let’s create a task to combine everything together:

grunt.registerTask('CI-E2E', ['shell:xvfb', 'env:xvfb', 'protractor:run', 'shell:xvfb:kill']);

After this, a can simply run


and all your UI tests will run on top of Xvfb. That’s it.

AngularJs, Grunt, Optimizations, Performance

Improving performance in production environment

By default, when we create data-bound elements, angular attaches additional information about the scope and the bindings to the DOM node, and then applying ng-binding CSS class to the data bound element. Debuggers (such as Batarang) and test frameworks (Like Protractor) requires this information to be able to run.

Let’s try it out by ourselves

We will setup a simple app with a controller and a directive with isolated scope.


<div ng-controller="myController">controller</div>
<isolated-scope data-binding="isolated scope"></isolated-scope>


app.directive('isolatedScope', function() {
  return {
   scope: {
     binding: "@binding"
   template: "{{binding}}"

app.controller('myController', function($scope) {
  $scope.location = "You are in a controller";

Next, if we’ll execute in the console:


We will get the scope of our controller.

$ChildScope: null
$$childHead: null
$$childTail: null
$$listenerCount: Object
$$listeners: Object
$$nextSibling: Scope
$$prevSibling: null
$$watchers: null
$id: 2
$parent: Scope
location: "You are in a controller"

And if we try –


We will get the isolated scope of the directive

$$childHead: null
$$childTail: null
$$destroyed: false
$$isolateBindings: Object
$$listenerCount: Object
$$listeners: Object
$$nextSibling: null
$$phase: null
$$prevSibling: ChildScope
$$watchers: Array[1]
$id: 3
$parent: Scope
$root: Scope
binding: "isolated scope"

OK, that’s informative. So what’s the problem?

The problem is, that according to Angular’s running in production document, this info may come at a cost of “significant” performance loss.

Luckily, the solution is quite simple. Since you need this information while developing and debugging, but you do want to turn it off in production,
you can easily switch it on/off in the config phase of the application, and control this configuration with your build tool. Let’s see an example –

First, we configure debugInfoEnabled during the config phase of our application.

// application's config constant
angular.module('myApp').constant('myConfig', {
	enableAngularDebugInfo: true

// setup necessary changes in config phase 
angular.module('myApp').config(function ($urlRouterProvider, myConfig) { 

The value enableAngularDebugInfo should be true by default, since we need it for development.
Next, we should disable it when building the application for production. I will demonstrate an example with Grunt, but you can do it with Gulp, Cake, Broccoli or any other task runner.

Configuring GruntFile to disable debugInfoEnabled in production

For simplicity purposes, i have removed from the GruntFile all commands that don’t directly relevant to disabling AngularDebugInfo:

module.exports = function (grunt) {

    // Project configuration.
        'string-replace': {
            disableAngularDebugInfo: {
                options: {
                    replacements: [{
                        pattern: 'enableAngularDebugInfo: true,',
                        replacement: 'enableAngularDebugInfo: false,'
                src: 'temp/app.full.js',
                dest: 'temp/app.full.js'

    // for build task, run string-replace.
    grunt.registerTask('build', ['string-replace']);

As you can see, we used the neat grunt-string-replace to replace true to false when running the build command. Obviously the actual build command will contain many more tasks (tests, jshint etc’), string-replace it’s only one of them.

And that’s it, now in your app.full.js file, angularDebugInfo will be disabled, so you can keep on developing while boosting up your applications performance in production environment.