Hello everyone. In this article, I’m going to write about the initial way of dockerizing your beloved Cucumber-Capybara tests. docker
So why would you do it? docker
Well, the main reason is portability. With this approach people(or CI/CD build servers) who want to run these tests, you don’t need to install anything. It’s easy to maintain and acts as a base for improvement like parallelisation.
Here is the link for the project: https://github.com/testhive/Cucumber-Capybara-Template
What is this project?
The project is just a simple template for a cucumber based test suite. There are intentional failures in order to demo how it takes a screenshot.
* In order to enable screenshot taking you should include a runtime parameter in your cucumber command or in your run configuration, such as;
cucumber features –format HTML –out <your-file-name-here>.html
Functional features of the project
- Has a sample for a GUI test with capybara
- Has a sample for a service test
- Takes screenshots of the failures with GUI tests and puts them into the HTML report
(you can see the code in support/hooks.rb)
Let’s have a detailed look into our project structure;
Features folder: This is where our tests are. I’m not going to go into detail about this folder because a lot of people (including myself) have described it a number of times.
Dockerfile: It imports an official ruby 2.2.2 image, copies gemfile and gemfile.lock to builds project dependencies, installs XVFB, firefox and geckodriver, copies your features folder, copies cucumber-command.sh and executes it while creating a XVFB instance to run GUI tests on. Let’s go over this file line by line;
We’re using the official ruby 2.2.2 image as a baseline. I’m sure the Lite and Alpine versions can be configured to run properly but for time limitations I went for the simplest (yet largest) solution.
RUN mkdir /app
We create a new workspace folder on the docker image for our feature files.
RUN gem update
ADD Gemfile /app/Gemfile
ADD Gemfile.lock /app/Gemfile.lock
Let’s update our stock gems, copy our Gemfile and Gemfile.lock into the image for our dependency management.
RUN bundle install
RUN apt-get update && apt-get install -y --fix-missing iceweasel xvfb
In these two lines above, we make a bundle install to install our gem dependencies according to our Gemfile. In the second line, we install Firefox (iceweasel) and XVFB for our GUI tests. XVFB is a virtual frame buffer which will enable Firefox to be run as a GUI application. We can use headless browsers without XVFB, but that wouldn’t be the same as testing on a real browser.
ENV GECKODRIVER_VERSION v0.13.0
RUN mkdir -p /opt/geckodriver_folder
RUN wget -O /tmp/geckodriver_linux64.tar.gz https://github.com/mozilla/geckodriver/releases/download/$GECKODRIVER_VERSION/geckodriver-$GECKODRIVER_VERSION-linux64.tar.gz
RUN tar xf /tmp/geckodriver_linux64.tar.gz -C /opt/geckodriver_folder
RUN rm /tmp/geckodriver_linux64.tar.gz
RUN chmod +x /opt/geckodriver_folder/geckodriver
RUN ln -fs /opt/geckodriver_folder/geckodriver /usr/local/bin/geckodriver
OK so this section is all about downloading the Gecko driver for Firefox. We set an environment variable to use in versioning (there might be a better way to do this dynamically but still you would like to use a specific version to avoid not tested new driver versions), create a folder for the driver, download the compressed driver with wget (I tried curl before but had some problems), unzip it to the folder we created, delete the compressed file, make the executable, well executable and finally create a symbolic link in bin folder.
ADD features /app/features
ADD cucumber-command.sh /app/cucumber-command.sh
RUN chmod a+x /app/cucumber-command.sh
In these 3 commands, we simply copy our features folder (where our tests are) and the cucumber-command.sh (we’ll talk about it later) into our working directory, make cucumber-command executable and run it.
CMD xvfb-run --server-args="-screen 0 1440x900x24" bash cucumber-command.sh
This is our final command that will launch an XVFB server with 1440×900 resolution and run cucumber-command on it.
Gemfile: In our Gemfile, we hold our ruby version for the project, the gem sources from where we’re going to install the gems and the gems themselves. Along with the Gemfile.lock file these two files determine our dependencies. In the lock file are the versions of the gems that we use. So the idea is to build and test the project locally while implementing your tests and then use the same setup in the docker image via adding these two files into it.
cucumber-command.sh: I used this shell script to hold the cucumber runner command itself. It’s a way that I used to de-couple the cucumber command and the dockerfile. You can modify it to specify
docker-test-run.sh: This shell script serves as a test runner for the project. Here is how this project runs;
In order to execute the tests, all you need to do is clone the project and run “docker-test.run.sh”. When you run the docker-test-run.sh it performs the following:
“docker build -t longlost/cukes-template .”
–> The docker image is built.
“docker run longlost/cukes-template”
–> The Image is run which includes executing the cucumber-command.sh
docker ps -l -q:/app/docker-html-report.html docker-html-report.html”
–> The HTML report which is generated as a result of the test run is copied into the host system (your local).
So there you have it folks, this is my first attempt to dockerize a Cucumber Test. Please feel free to improve it 🙂