How to run cucumber selenium tests in chrome headless
As many of us already know continuous integration becomes very important part in software development. But in order to be able to do continuous delivery we need a stable automated test suite that runs against our app and gives us a fast feedback. Many of you choose to run selenium tests using headless browsers like phantomJs or htmlUnit but that is not a real browser and you might end up with bugs that you didn’t caught during your test execution. That’s why a quick good solution is to run your cucumber selenium tests in chrome headless browser inside docker container.
Im not going to explain how to setup docker , you can do it following their documentation which is very well explained. In this article I’m going to cover how to setup your docker file in order to achieve headless execution using google chrome browser and on the next article I’m going to cover how you can have multi threading execution using docker and Jenkins pipeline using groovy scrips.
Docker file configuration
# Base the image off of the latest pre-built ruby image
FROM ruby:2.4
ENV DEBIAN_FRONTEND noninteractive
# make and switch to the /code directory which will hold the tests
RUN mkdir /code
WORKDIR /code
RUN mkdir output && chmod a+w output && mkdir output/logs
# move over the Gemfile and Gemfile.lock before the rest so that we can cache the installed gems
ADD Gemfile /code/Gemfile
ADD Gemfile.lock /code/Gemfile.lock
# upgrade to latest version of bundler
RUN gem install bundler -v 1.13.6
# install all the gems specified by the gemfile
RUN bundle install
RUN echo "deb http://dl.google.com/linux/chrome/deb/ stable main" | tee -a /etc/apt/sources.list
RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -
RUN apt-get update && \
apt-get -qq -y install xvfb iceweasel \
libxpm4 libxrender1 libgtk2.0-0 libnss3 libgconf-2-4 \
libpango1.0-0 libxss1 libxtst6 fonts-liberation libappindicator1 xdg-utils
# copy .deb package *only* into the container
ADD drivers/chrome64_55.0.2883.75.deb /code/drivers/google-chrome-stable_current_amd64.deb
# install google chrome stable
RUN dpkg -i /code/drivers/google-chrome-stable_current_amd64.deb
RUN apt-get install -f
RUN apt-get update
RUN apt-get -y install \
xvfb gtk2-engines-pixbuf \
xfonts-cyrillic xfonts-100dpi xfonts-75dpi xfonts-base xfonts-scalable \
imagemagick x11-apps zip
# start XvFB server
RUN Xvfb -ac :99 -screen 0 1680x1050x24 &
RUN export DISPLAY=:99
# copy over the rest of the tests
ADD . /code
ENTRYPOINT ["cucumber"]
Keep in mind that this docker file is exclusively for ruby environment and cucumber seleniun tests execution , if you are in a java or any other environment you might have to do some small adjustments on the image.
The original docker file script was had the following content and we adjusted it on our needs.
#!/bin/bash
#
# Bash script to setup headless Selenium (uses Xvfb and Chrome)
# (Tested on Ubuntu 12.04) trying on ubuntu server 14.04
# Add Google Chrome's repo to sources.list
echo "deb http://dl.google.com/linux/chrome/deb/ stable main" | sudo tee -a /etc/apt/sources.list
# Install Google's public key used for signing packages (e.g. Chrome)
# (Source: http://www.google.com/linuxrepositories/)
wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
# Update apt sources:
sudo apt-get update
# Install Python, pip, Selenium:
#sudo apt-get -y install python python-pip
#sudo pip install selenium
different way to get chromedriver and selenium java jar:
sudo apt-get -y install default-jre # if not installed yet
sudo npm install protractor -g
sudo webdriver-manager update
sudo ln /usr/lib/node_modules/protractor/selenium/chromedriver /usr/bin/chromedriver
#sudo apt-get -y install unzip
# Download/Install chromedriver
# (http://code.google.com/p/chromedriver/):
#
# For x86:
#wget -c http://chromedriver.googlecode.com/files/chromedriver_linux32_2.1.zip
#unzip chromedriver_linux32_2.1.zip
#
# For x86-64:
#wget -c http://chromedriver.googlecode.com/files/chromedriver_linux64_2.1.zip
#unzip chromedriver_linux64_2.1.zip
# Neither creating symbolic link nor adding dir to $PATH worked for me
# in a Vagrant VM. So, let's blatantly copy the binary:
#sudo cp ./chromedriver /usr/bin/
#sudo chmod ugo+rx /usr/bin/chromedriver
# Install Google Chrome:
sudo apt-get -y install libxpm4 libxrender1 libgtk2.0-0 libnss3 libgconf-2-4
sudo apt-get -y install google-chrome-stable
# Dependencies to make "headless" chrome/selenium work:
sudo apt-get -y install xvfb gtk2-engines-pixbuf
sudo apt-get -y install xfonts-cyrillic xfonts-100dpi xfonts-75dpi xfonts-base xfonts-scalable
# Optional but nifty: For capturing screenshots of Xvfb display:
sudo apt-get -y install imagemagick x11-apps
# Make sure that Xvfb starts everytime the box/vm is booted:
echo "Starting X virtual framebuffer (Xvfb) in background..."
Xvfb -ac :99 -screen 0 1280x1024x16 &
export DISPLAY=:99
# Optionally, capture screenshots using the command:
#xwd -root -display :99 | convert xwd:- screenshot.png
Assuming you have a chromedriver instance in your env.rb that looks similar with the following :
Capybara.register_driver :chrome do |app|
client = Selenium::WebDriver::Remote::Http::Default.new
client.read_timeout = 120
Capybara::Selenium::Driver.new(app, :browser => :chrome, http_client: client)
end
Capybara.default_driver = :chrome
Capybara.javascript_driver = :chrome
Capybara.default_max_wait_time = 60
Inside env.rb your headless code should be :
if $headless_server.nil?
if !ENV['IN_BROWSER']
require 'headless'
# allow display autopick (by default)
# allow each headless to destroy_at_exit (by default)
# allow each process to have their own headless by setting reuse: false
# $headless_server = Headless.new(reuse: true)
$headless_server = Headless.new(reuse: true, destroy_at_exit: false)
$headless_server.start
log_message("Process[#{Process.pid}] started headless server display: #{$headless_server.display}")
log_message(Capybara.default_driver, "default driver" + "######################################")
end
end
at_exit do
unless $headless_server.nil?
log_message("Process[#{Process.pid}] destroying headless server on display: #{$headless_server.display}")
$headless_server.destroy
end
end
As I mentioned in the top of the article , next topic will be related parallel execution using jenkins pipeline and docker.
Happy testing!
The post How to run cucumber selenium tests in chrome headless appeared first on TestingRepository.