Running Cucumber Features Without a Display

Written by Sarah Mei - - Aggregated on Friday December 17, 2010
Tags: cucumber, ruby, selenium

I’ve been helping out with the Diaspora project, an open source social network that gives you control over your own data.

When I first started poking around the codebase a few months ago, they’d just started writing a few cucumber selenium integration tests – which of course I want to encourage! – but they weren’t running them on their continuous integration box. And if you aren’t running them on CI, you can’t really call them tests…

It’s not that the developers were lazy; it’s just that Diaspora’s CI box is an ubuntu server instance that doesn’t even have xwindows. There’s no way to attach a display, and without a display, a browser won’t run. So how can you run selenium features that have to actually open a browser window and click on stuff?

I’m glad you asked!

You set up a virtual framebuffer – essentially a simulated display – and run your features in there. Here’s how I got this going.

Step 1: Install Crap

Yeah, you need xwindows, and a bunch of other stuff. I’m not a frequent linux user, so I was surprised that a lot of these commands appeared to fail, with extremely lengthy output about how such-and-such dependency could not be installed, or compiled, or resolved, or kafloozled, or whatever. But then when I ran the programs that supposedly weren’t installed, they worked fine. …thanks, ubuntu?

sudo aptitude install xubuntu-desktop
sudo aptitude install exaile
sudo aptitude install gconf2
sudo aptitude install xvfb
sudo aptitude install firefox

Step 2: Verify Your Virtual Framebuffer

I like the phrase “virtual framebuffer.” It’s very computer science, and using it makes me feel smart. But really, it’s just a display that gets rendered in memory, but not output to any monitor. Programs that require the ability to create windows, such as Firefox, need a display to run in – but they’ll take any old display. If you give Firefox a virtual framebuffer, it’s perfectly happy and treats it like any other display, even though no one can see it.

So let’s verify we have everything set up to run one. This magic incantation starts one on display port :99.

 Xvfb :99 -ac -screen 0 1024x768x16

In another shell, run this one, which opens Firefox to example.org inside the virtual display you’re running in the original shell.

DISPLAY=:99.0 firefox http://example.org

Firefox is now open to example.org, the world’s most boring webpage. Really! Let’s prove it by taking a screenshot in a third shell.

xwd -root -display :99.0 -out xwdout

Your screenshot is now in a file called xwdout. Sadly, this is not an image format that normal image viewers can see, so let’s convert it to a jpeg.

convert xwdout screenshot.jpg

Using your favorite sftp program, retrieve screenshot.jpg and have a look at it. It should look something like this:

That boxy UI, those icons from 1995...it could only be linux.

Ta-da! You have evidence of this so-called “virtual” framebuffer. Now all we have to do is set it up so to start before we run the tests, and stop once the tests are done.

Step 3: Adventures in Shell Scripting

This goes in your /etc/init.d, and will give you ULTIMATE POWER, if ultimate means you can start and stop a virtual framebuffer on display port :99.

Now you just need a rake task that starts the display, passes the port info to the tests, and then stops it.

And just in case you have to get this running with rvm, here’s the shell script that cc.rb calls to kick off a Diaspora build on ruby 1.8.7.

I’ve had to set this up twice, now, but there are a lot of moving parts. If you try this and notice something I forgot, please let me know.

Enjoy your headless cucumbers…

(I wonder what kind of google search results that will get me.)


« CruiseControl.rb and RubyGems 1.5.2 - Sarah Mei

Ondřej Mirtes - Slevomat Coding Standard »