Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Testing Your Rails Application With Docker

DZone's Guide to

Testing Your Rails Application With Docker

A tutorial on running tests on Rails apps with Docker containers, as well as browser and parallel container tests.

· DevOps Zone
Free Resource

Download the blueprint that can take a company of any maturity level all the way up to enterprise-scale continuous delivery using a combination of Automic Release Automation, Automic’s 20+ years of business automation experience, and the proven tools and practices the company is already leveraging.

In my last article, I showed you how to move a Rails development environment to Docker (and Docker Compose). This time, I want to expand on that and discuss some improvements regarding testing your Rails application.

Running your basic test suite is done quite easily. With the configuration from my last post, you can simply run the following commands to spin up the environment, create and seed the database, and run your test suite.

docker-compose up
docker-compose run -e "RAILS_ENV=test" app rake db:create db:migrate
docker-compose run -e "RAILS_ENV=test" app rake test


This is basically the same way you would run your tests locally and though it might speed up test times a bit (depending on the hardware Docker is running on), it isn’t a huge improvement.

But you could run the tests in multiple containers at the same time.

Running Individual Tests

As with the app running locally, you can run individual test suites by specifying the filename in the run command.

docker-compose run -e "RAILS_ENV=test" app rspec spec/path/to/spec.rb


Running Tests in Parallel Containers

If your Docker host is beefy enough, you could also run your tests in parallel using multiple containers. There are tools like parallel_tests available, which allow you to run your tests in parallel on a single machine; you might want to reuse those as well.

Browser Testing

If you want to run tests via Capybara or a similar tool, you can simply extend your Dockerfile to include the necessary browsers as well as the xfvb package, which provides a virtual display server.

...
# The Firefox package is called Iceweasel on Debian, but still provides the
# `firefox` binary.
RUN \
  DEBIAN_FRONTEND=noninteractive \
  apt-get install -y \
    chromium \
    iceweasel \
    xvfb
...

Include the webdriver in your Gemfile, and you’re good to go. I’d also recommend taking a look at the headless gem, which provides an easy to use wrapper around xvfb and allows you to capture images or video as well.

Alternatively you could switch to using PhantomJS, which provides a headless version of WebKit and doesn’t require any additional packages. Install it by adding the following commands to your Dockerfile.

...
ENV PHANTOMJS_VERSION=1.9.8
RUN \
  cd /usr/local/share && \
  wget https://phantomjs.googlecode.com/files/phantomjs-${PHANTOMJS_VERSION}-linux-i686.tar.bz2 && \
  tar xvf phantomjs-${PHANTOMJS_VERSION}-linux-i686.tar.bz2 && \
  rm phantomjs-${PHANTOMJS_VERSION}-linux-i686.tar.bz2 && \
  ln -s /usr/local/share/phantomjs-${PHANTOMJS_VERSION}-linux-i686/bin/phantomjs /usr/local/bin/phantomjs

Note: We’re using version 1.9.8 of PhantomJS because Linux binaries for version 2 aren’t yet available. If you want to use version 2, you’d need to compile it yourself, but you could then use the above command to download and install it.

Running Development/Test Only Dependencies

If you require dependencies, which should only be running in your test development or environment, you can quite easily add a new container definition in the docker-compose.yml and adapt your configuration accordingly.

For example, Discourse uses Mailcatcher during development. In a traditional setup, you’d be required to install the software on your development computer. However, it becomes even easier with the containerized setup.

Adapt your application definition as detailed below (the development.rb configuration already includes the configuration to send mails via the port defined by Mailcatcher, so you don’t need to change it at all).

app:
  ...
  links:
    ...
    - mailcatcher
...
mailcatcher:
  image: schickling/mailcatcher
  ports:
    - "1080:1080"

Once you restart the environment, you can open the Mailcatcher web interface on the IP of your Docker host and see any mail sent via your application.

Docker on Codeship

Like I mentioned in my last post, Codeship is currently preparing a Docker-based CI infrastructure as well. We’ll use Docker Compose (with some extensions) to define your test environment and then have a separate YAML-based configuration for configuring which steps to run.

The platform is still under development, so the available options aren’t set in stone, but the following configuration would run various tests on multiple containers for the Discourse repository.

# codeship-services.yml
app:
  build:
    image: codeship/discourse
    dockerfile_path: Dockerfile
  environment:
    RAILS_ENV: test
  links:
    - postgresql
    - redis
  volumes_from:
    - data
postgresql:
  image: postgres:9.4
redis:
  image: redis:3.0
data:
  image: busybox
  volumes:
    - /data

Combined with the following step definition, we will run your tests in three Docker containers in parallel.

# codeship-steps.yml
- type: parallel
  service: app
  steps:
    - command: bundle exec rspec
    - command: bundle exec rake plugin:spec
    - command: bundle exec rake qunit:test

Head over to Codeship Docker Beta to sign up for the beta.

Download the ‘Practical Blueprint to Continuous Delivery’ to learn how Automic Release Automation can help you begin or continue your company’s digital transformation.

Topics:
devops ,rails ,docker ,testing

Published at DZone with permission of Moritz Plassnig, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}