Twice in the past year I have struggled to get continuous builds and test coverage set up on Travis and Coveralls (respectively). The first time was so frustrating that I just gave up, but last week I finally got things working! I thought it would be helpful to describe what worked (and why).
Probably the information I put here will slowly become outdated, but for the
most recent copy of a working
.travis.yml file, please see the setup at
Here are the contents of the Travis config file; I’ll break things down (at least as far as I understand them) bit by bit.
sudo: false language: python python: - "2.7" - "3.4" cache: apt addons: apt: packages: - libatlas-dev - libatlas-base-dev - liblapack-dev - gfortran before_install: - wget http://repo.continuum.io/miniconda/Miniconda-latest-Linux-x86_64.sh -O miniconda.sh - bash miniconda.sh -b -p $HOME/miniconda - export PATH="$HOME/miniconda/bin:$PATH" - conda update --yes conda install: - conda install --yes python=$TRAVIS_PYTHON_VERSION pip numpy scipy nose - pip install pep8 python-coveralls - pip install . script: - THEANO_FLAGS=floatX=float32 nosetests --with-coverage --cover-package=theanets --logging-level=INFO after_success: - coveralls
sudo: false line enables builds on the new Docker infrastructure for
language: python line and the
python: section enable a
The next two sections (the
cache: apt line and the
addons: apt: section)
enable us to install some additional Ubuntu packages to our test environment. In
this case, the config file installs packages that are needed to support the
before_install section is where the magic starts. It first downloads the
latest version of the
- wget http://repo.continuum.io/miniconda/Miniconda-latest-Linux-x86_64.sh -O miniconda.sh
Next it runs the script and adds the installed environment to the
- bash miniconda.sh -b -p $HOME/miniconda - export PATH="$HOME/miniconda/bin:$PATH"
Finally, the config updates the Conda environment to the latest release. This
appears to be necessary because
miniconda releases sometimes lag behind
- conda update --yes conda
So far, everything has come from the Travis CI Python docs
and the Conda Travis docs. The
Travis docs are not super helpful by themselves if your project requires
scipy manually using
pip makes your builds take
forever, not to mention being a colossal waste of a fantastic, free
computational resource. I found the Conda docs to be super confusing since the
focus is more on using Conda to distribute packages, while I just wanted to use
Conda for Travis builds.
Anyway, the build environment is set up and ready to install things! Here is where things got pretty tricky.
I use the
install section of the build config to install packages that
theanets needs for testing. This is confusing because now that
set up on the Travis build machine, there are actually two environments where
Python packages can be installed: the Travis environment, and the Conda one. The
Conda environment is sort of a neglected stepchild in the Travis environment; if
you don’t explicitly enable it, the Travis environment will be used.
With that in mind, the config file ventures into risky territory by installing some packages built specially for Conda:
- conda install --yes python=$TRAVIS_PYTHON_VERSION pip numpy scipy nose
There are two very important packages on this line:
are both important for related reasons that seem to revolve around paths in the
conda install pip. If you don’t, then if you later try to
pip install foo, the version of
pipthat serves your request will install things into the Travis environment, not the Conda one! Installing
condaensures that the
pipthat serves your request will know to put things in the Conda environment.
noseto run your tests, then you also need to
conda install nose! The reason here seems to be quite similar to the first point: if you don’t install
conda, then the version of
nosethat runs your tests will look in the Travis environment, not the Conda one! (This took me a few hours of banging-head-on-desk to figure out.)
The other two packages are just dependencies of my project. No biggie.
Next, the config installs a couple of additional dependencies using
- pip install pep8 python-coveralls
pip? As far as I understand, it’s because Conda doesn’t have access to
all of the packages on the Python package index. I’m not sure why this is the
case, but if you try to
conda install these, it won’t work. Again, this only
works here because we did
conda install pip above.
Finally, the config sets up the actual
theanets package for testing:
- pip install .
With that, the tests are ready to run. I use
nose to run tests for
theanets; until I installed
conda install, this step was
giving me all sorts of grief.
script: - nosetests --with-coverage --cover-package=theanets --logging-level=INFO
This line is prefaced by
THEANO_FLAGS=floatX=float32 to set up an important
Theano configuration variable—if you don’t set this explicitly, then your
tests involving Theano might fail in different environments based on the types
of floating-point data that you use.
Finally, the coveralls tool uploads code coverage results from your tests, and then you get lovely clickable source maps showing where your test coverage needs work.
after_success: - coveralls
After I got things working, I spent a couple hours increasing test coverage for the project. It’s quite the motivator to see that big red number come up for your project!
Happy coding (and testing)!