In the popular series on how technical decisions are made, we will see Today why DjaoDjin picked django-jenkins, phantomjs, casperjs and django-casper to build its continuous integration infrastructure on.
Continuous integration for Django projects
Python is a great language. It makes it quick to get to working code in production. Unfortunately like many dynamic programming languages, issues arise when you start to add features and rework the code base. With a static type checking language like C++, the compiler would caught stupid mistakes like variable name that wasn't updated all the places it is used, or like a function parameter that used to be an integer and is now a list of integers.
Welcome to the world of extensive testing. If you are looking to deploy code changes at the pace required to run a webapp, continuous integration becomes rapidly an important aspect of the development cycle.
django-jenkins is a perfect start if, like us, you are running django and jenkins. The only unfortunate hic-hup so far is the absence of support for behave. That is unfortunate because we chose behave over lettuce for various reasons.
Since behave accepts a --junit command line flag, it is though possible to integrate and jenkins directly, as a subsequent command.
$ python manage.py jenkins $ behave --junit --junit-directory ../reports
SIDE NOTE: There is a django-behave project. Unfortunately using it will remove the ability to run standard django testsuites - or more accurately from reading comments in the code - mixing django-behave and tests based on unittest hasn't been implemented yet. There has been no update to the repository in eight months as of writing this post.
The first intuition was to use python bindings to selenium, a browser automation framework.
$ pip install selenium --upgrade # Download the webdriver for your browser $ unzip ~/Download/chromedriver_mac_26.0.1383.0.zip $ mv chromedriver /usr/local/bin $ export PATH=$PATH:"/Applications/Google Chrome.app/Contents/MacOS"
Selenium is quite heavy weight. It requires to launch the browser executable and that will trigger GUI windows popping-up on your screen. You might be able to install all the required packages to run a X11 server with no display attached on your continuous server virtual machine but that seems like overkill and like a potential rat hole of package dependencies.
Welcome to phantomjs, the headless webkit engine.
We thus reverted our first attempt of using phantomjs with jasmine and djangojs and started to look again for a more suited solution. That is how a few searches later we ended-up on casperjs and django-casper. By itself casperjs generates junit xml output. You can thus use casperjs straight from the command line in your jenkins shell.
$ cat hellotest.js casper.test.comment('this is an hello test'); casper.test.assertTrue(true, "YEP"); casper.test.done(); $ casperjs test --xunit=./test-result.xml hellotest.js
Once integrated into django through a django-casperjs wrapper, your tests look and behave like regular django tests. Hence they integrate perfectly with manage.py test and django-jenkins. Excellent!