Two Travis CI Solutions: Ivy Dependencies and Headless Testing
One of last week’s projects was setting up Travis CI, a hosted continuous integration service that’s free for open source projects. Even if you haven’t heard about Travis (as I hadn’t), you’ve probably already seen the service on Github—it’s responsible for the green and red build status icons at the top of many project READMEs.
After every push to a remote repo, Travis builds your project, runs the test suite, and sends off a notification with the results. Once it’s configured, it’s a great way to ensure that even if your project is unfinished, the published code will work correctly for anyone who pulls the repo.
The official Travis docs are close to comprehensive, but I ran into a few catches getting everything set up (and have an inbox full of failed build notifications to prove it). Hopefully these solutions will rescue someone else from a frustrating afternoon.
Resolving Ivy dependencies
My Tic Tac Toe project uses Ivy to manage build dependencies, and my ant build script includes a standard snippet that downloads Ivy if it’s not available locally:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
|
If your build and test targets are set to depend on the init-ivy
task, the script will ensure that Ivy resolves itself and the
project’s other dependencies correctly. Telling Travis how to build
and test a project is as simple as writing a few lines of YAML. For
example:
1 2 3 4 5 6 |
|
This tells Travis the project language (which comes with its own
default settings),
points to ant resolve
as the command necessary to resolve
dependencies, and describes the target Java versions to test against.
But my builds failed with the following mysterious error:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
|
Even though ant was correctly downloading an ivy jarfile, the build script failed to find it. The answers to my Stack Overflow question explained that this was related to the order in which jars are loaded to the Java classpath. The easiest solution is to run ant twice, once to download ivy, and again to build and test the project.
Once the source of this error was cleared up, the solution was simple.
Adding a before_install
script to my Travis build ensured that ivy
would be downloaded before trying to build the project. This meant
adding just one line to my .travis.yml
:
1 2 3 4 5 6 7 |
|
There are a number of other options to run scripts at different times in the Travis lifecycle. Check out the rest of the docs here.
Headless testing with xfvb
My Travis builds worked nicely until I started adding a Swing view to
my Tic Tac Toe project. Although the tests would run and pass locally,
Travis threw a java.awt.HeadlessException
as soon as it tried to run
the test suite. The Travis docs explain using a tool called xvfb (X
Virtual Framebuffer) to simulate a windowing system and run headless
tests, but warn that “you need to tell your testing tool process”
exactly how to use it.
Exactly how to do this wasn’t clear, but after fiddling with JVM startup arguments and
trying to shell out from inside ant, I discovered that the solution
was dead simple: just add the recommended arguments to .travis.yml
,
and ant and JUnit will take care of the rest. Here’s my final
.travis.yml
, including the solutions to both problems.
1 2 3 4 5 6 7 8 9 10 |
|