Sea Sprint 2012 Report-Out

A Python snob’s adventures in JS testing land.

I was surprised and excited to receive an invite to the first Sea Sprint from Chris Calloway. When I read that it was also being put on by Andrew Leeb and Ian Anderson of Anderson Leeb, Inc. I knew I wanted to go. I’d had the chance to hang out with them at the Plone Symposium East 2012 and the sprints before and after and enjoyed their company a lot. When I heard I could get my airfare sponsored, I knew I absolutely had to go. Not to geek out, but this was the first sprint travel sponsorship and I’m pretty excited about that.

Location and Hosting

This was one of the better organized sprints I’ve been to. Flights were coordinated to arrive and depart within 1-2 hours of each other making rides around arrival and departure fast and easy. We got to Oak Island, a beautiful and very long barrier island not far from the border with South Carolina, Friday afternoon and had some time to go to the beach and go for a quick swim.

I’d never been to the atlantic coast on either side nor had I been to the Carolinas before and have always wanted to. Living on the north Pacific for so long, I’ve never swam in warm ocean water before, very interesting. The two beach houses were right on the beach with deck walks extending out to the dunes and a covered outside area. The beds were comfy and there were great views all the way around. It was off-season but the temperatures were still warm to temperate so there were no crowds and great weather.

Chris Calloway is simply an amazing cook. He made breakfast, lunch, and dinner for 14 people almost entirely by himself both Saturday and Sunday. As if the scope of that weren’t enough, these meals were top-notch. Seriously, the food really has to be called out here. Thanks so much Chris!

The Sprint

After a delicious dinner at a local Thai restaurant sponsored by Dylan Jay, David Glick did an excellent job facilitating the planning of the sprint work. This was the most efficient sprint planning I’ve been to, great job David! Before we went to bed Friday night, we all knew what we were working on the next day.

My biggest hope for my participation in this sprint was to get better at JavaScript/ECMASCript while still contributing towards the goals of the sprint. I’ve been confounded by JS much more than I’d like and have never really been able to develop the proficiency I’d like with it. Since I learn best by writing tests with a good testing framework, I decided to work on writing JS unit tests for the bits of Deco and the toolbar that are JS heavy:

I started working with Rob Gietema, someone whose mad JS skills I’ve always admired, and Clayton Parker, who is much in the same boat as I when it comes to JS skills. Rob introduced us to Buster.JS, a new cross-browser JS unit testing framework that everyone seems to prefer to use. Clayton began writing tests for JS and I began looking into ways to integrate the Buster.JS tests into our general testing story.

In Plone land, our buildouts do a pretty good job of serving two testing purposes:


Deployed locally and give individual developers a test runner they can use to run some or all of the tests before they commit changes.

Continuous Integration

Deployed on our CI server to run all tests and catch regressions and interactions.

I set my sights on providing something that served the same two purposes for JS unit tests.

When we started, running the Buster.JS tests was a fairly manual process and done in a very different way than running our other tests. One had to:

  1. change directories

  2. fire up the buster-server

  3. capture a browser slave

  4. run buster-test

I started working on automating as much of this as possible and integrating it with our buildout test runners if possible.

I didn’t make much progress on the first day, Saturday. In the morning, I was mostly learning how things were done and understanding the architecture. After lunch, I had a pretty good idea of what I wanted to do, so I began trying to understand the Buster.JS internals enough to add what we needed. That turned out to be a pretty deep rabbit hole for me at my JS skill level so in the evening, I abandoned that effort and started writing a simple Python script that would do the all the steps for you and finally shutdown the browser slave and buster-server. At least I was getting somewhere.

With that experience under my belt, I knew that what we needed was:

Look familiar? These are all the services provided by zope.testrunner that we make so much use of in our buildouts.

There was one more issue in that capturing browser slaves by just running firefox meant that buster-test runs could potentially be polluted by any extensions, themes, or other add-ons in your Firefox profile. The same would be in similar senses for other browsers. This is also a familiar issue, which is precisely why selenium.webdriver does a lot to invoke the browsers it’s driving in an isolated way.

So on Sunday I set about integrating the running of Buster.JS tests with zope.testrunner and to capture browser slaves using selenium.webdriver. I did this in a new package, buster-selenium. By Sunday night, I had it integrated with the testrunner in buildout.deco such that Buster.JS tests would be run alongside the Python unittest tests. By default it would use selenium.webdriver to capture a Firefox slave and use it’s JS engine to run the tests. I also added a part to run Buster.JS unit tests and coverage reports and output XML that could be integrated into our Jenkins CI. Finally, I added support for capturing browser slaves using Selenium Grid. That was enough to release buster-selenium.

There is more that can be done:

Let me know if you think those would be valuable. Hearing what the interest is will make it more likely that I’ll get around to it.


This was a really great sprint, we got a lot done and I feel like I was able to make a worthy contribution. I’m really glad that the organizers are thinking seriously about doing this every year.

Updated on 26 September 2012

Imported from Plone on Mar 15, 2021. The date for this update is the last modified date in Plone.


comments powered by Disqus