{"id":6574,"date":"2017-08-18T02:25:19","date_gmt":"2017-08-18T06:25:19","guid":{"rendered":"https:\/\/qxf2.com\/blog\/?p=6574"},"modified":"2019-01-24T08:24:13","modified_gmt":"2019-01-24T13:24:13","slug":"preparing-a-docker-image-for-running-selenium-tests","status":"publish","type":"post","link":"https:\/\/qxf2.com\/blog\/preparing-a-docker-image-for-running-selenium-tests\/","title":{"rendered":"Preparing a Docker image for running Selenium tests"},"content":{"rendered":"<p>Sometimes your team members complain about automated tests not working on their computer while you are able to run the automated tests at your end completely fine. We too, at <a href=\"http:\/\/www.qxf2.com\/?utm_source=docker-selenium-1&#038;utm_medium=click&#038;utm_campaign=From%20blog\">Qxf2<\/a>, have experienced this issue. Our automated tests run fine at our end but occasionally fail when they run on our colleagues and client machines. Invariably, we trace this sort of failure down to variations in the setup\/environment. So we looked to tackle this issue. We decided to build a <a href=\"https:\/\/www.docker.com\/\">Docker<\/a> container for running our Selenium tests. The process was very quick and we decided to help all our fellow testers by sharing how we went about doing it.<\/p>\n<p>This post assumes you already know a little about Docker. <\/p>\n<p><strong>NOTE:<\/strong> If you are just looking for a Docker image, you can skip &#8216;Step 1. Creating a Dockerfile&#8217; section and directly move on to the step 2 titled as &#8216;Build\/Pull the Docker image&#8217;. <\/p>\n<hr>\n<h3>Overview:<\/h3>\n<p>We will be performing the following steps:<br \/>\n1. Creating a Dockerfile<br \/>\n2. Build\/Pull the Docker image<br \/>\n3. Creating a container and running Selenium tests<\/p>\n<hr>\n<h3>Step 1. Creating a Dockerfile for running Selenium tests:<\/h3>\n<p>To get setup with Docker CE you can refer to this <a href=\"https:\/\/docs.docker.com\/get-started\/\">link<\/a>. To build a Docker image for running our Selenium tests, we needed to perform the following steps:<\/p>\n<ol>\n<li>Pull a Base image<\/li>\n<li>Install Xvfb virtual\/headless display<\/li>\n<li>Setup Chrome and Chrome driver<\/li>\n<li>Setup Firefox and Geckodrivers<\/li>\n<li>Install Python 2.7 and Python Pip<\/li>\n<li>Get your project code into image\/container and install requirements with help of pip and project requirements.txt file<\/li>\n<\/ol>\n<p>All the steps except the final one rarely change unless when we decide to change the version of software installed. However, your project code and requirements change frequently. So, we decided to come up with a base image for Selenium which includes the first 5 steps i.e Ubuntu, Chrome with Chrome driver, Firefox with Geckodriver, Xvfb, Python and Python\u00a0Pip. <\/p>\n<p>We will code these steps into a file called a Dockerfile. A <a href=\"https:\/\/docs.docker.com\/engine\/reference\/builder\/\">Dockerfile<\/a> is a text document that contains all the commands a user could execute on the command line to assemble an image. To build the base image for running the Selenium test, we wrote the following Dockerfile.<\/p>\n<p><strong>1. Pull a Base Image<\/strong><br \/>\nWe used Ubuntu 16.04. <\/p>\n<pre lang=\"python\">\r\n#Contents of Dockerfile\r\n#Dockerfile to build an image which supports testing our Qxf2 Page Object Model.\r\nFROM ubuntu\r\nMAINTAINER Qxf2 Services\r\n<\/pre>\n<p><strong>2. Install Xvfb virtual\/headless display<\/strong><\/p>\n<pre lang=\"python\">\r\n# Essential tools and xvfb\r\nRUN apt-get update && apt-get install -y \\\r\n    software-properties-common \\\r\n    unzip \\\r\n    curl \\\r\n    xvfb \r\n<\/pre>\n<p><strong>3. Setup Chrome and Chrome driver<\/strong><\/p>\n<pre lang=\"python\">\r\n# Chrome browser to run the tests\r\nRUN curl https:\/\/dl-ssl.google.com\/linux\/linux_signing_key.pub -o \/tmp\/google.pub \\\r\n    && cat \/tmp\/google.pub | apt-key add -; rm \/tmp\/google.pub \\\r\n    && echo 'deb http:\/\/dl.google.com\/linux\/chrome\/deb\/ stable main' > \/etc\/apt\/sources.list.d\/google.list \\\r\n    && mkdir -p \/usr\/share\/desktop-directories \\\r\n    && apt-get -y update && apt-get install -y google-chrome-stable\r\n# Disable the SUID sandbox so that chrome can launch without being in a privileged container\r\nRUN dpkg-divert --add --rename --divert \/opt\/google\/chrome\/google-chrome.real \/opt\/google\/chrome\/google-chrome \\\r\n    && echo \"#!\/bin\/bash\\nexec \/opt\/google\/chrome\/google-chrome.real --no-sandbox --disable-setuid-sandbox \\\"\\$@\\\"\" > \/opt\/google\/chrome\/google-chrome \\\r\n    && chmod 755 \/opt\/google\/chrome\/google-chrome\r\n\r\n# Chrome Driver\r\nRUN mkdir -p \/opt\/selenium \\\r\n    && curl http:\/\/chromedriver.storage.googleapis.com\/2.45\/chromedriver_linux64.zip -o \/opt\/selenium\/chromedriver_linux64.zip \\\r\n    && cd \/opt\/selenium; unzip \/opt\/selenium\/chromedriver_linux64.zip; rm -rf chromedriver_linux64.zip; ln -fs \/opt\/selenium\/chromedriver \/usr\/local\/bin\/chromedriver;\r\n<\/pre>\n<p><strong>4. Setup Firefox and Geckodrivers<\/strong><\/p>\n<pre lang=\"python\">\r\n# Firefox browser to run the tests\r\nRUN apt-get install -y firefox\r\n\r\n# Gecko Driver\r\nENV GECKODRIVER_VERSION 0.23.0\r\nRUN wget --no-verbose -O \/tmp\/geckodriver.tar.gz https:\/\/github.com\/mozilla\/geckodriver\/releases\/download\/v$GECKODRIVER_VERSION\/geckodriver-v$GECKODRIVER_VERSION-linux64.tar.gz \\\r\n  && rm -rf \/opt\/geckodriver \\\r\n  && tar -C \/opt -zxf \/tmp\/geckodriver.tar.gz \\\r\n  && rm \/tmp\/geckodriver.tar.gz \\\r\n  && mv \/opt\/geckodriver \/opt\/geckodriver-$GECKODRIVER_VERSION \\\r\n  && chmod 755 \/opt\/geckodriver-$GECKODRIVER_VERSION \\\r\n  && ln -fs \/opt\/geckodriver-$GECKODRIVER_VERSION \/usr\/bin\/geckodriver \\\r\n  && ln -fs \/opt\/geckodriver-$GECKODRIVER_VERSION \/usr\/bin\/wires\r\n<\/pre>\n<p><strong>Note:<\/strong> Please make sure you update the script to download the latest <a href=\"http:\/\/chromedriver.chromium.org\/downloads\">ChromeDriver<\/a> and <a href=\"https:\/\/github.com\/mozilla\/geckodriver\">geckodriver<\/a> versions<\/p>\n<p><strong>5. Install Python 2.7 and Python Pip<\/strong><\/p>\n<pre lang=\"python\">\r\n# python\r\nRUN apt-get update && apt-get install -y \\\r\n    python \\\r\n    python-setuptools \\\r\n    python-pip\r\n<\/pre>\n<p><strong>Putting it all together<\/strong><br \/>\nOur final Dockerfile looks like this:<\/p>\n<pre lang=\"python\">#Contents of Dockerfile\r\n#Dockerfile to build an image which supports testing our Qxf2 Page Object Model.\r\nFROM ubuntu\r\nMAINTAINER Qxf2 Services\r\n\r\n# Essential tools and xvfb\r\nRUN apt-get update && apt-get install -y \\\r\n    software-properties-common \\\r\n    unzip \\\r\n    curl \\\r\n    xvfb \r\n\r\n# Chrome browser to run the tests\r\nRUN curl https:\/\/dl-ssl.google.com\/linux\/linux_signing_key.pub -o \/tmp\/google.pub \\\r\n    && cat \/tmp\/google.pub | apt-key add -; rm \/tmp\/google.pub \\\r\n    && echo 'deb http:\/\/dl.google.com\/linux\/chrome\/deb\/ stable main' > \/etc\/apt\/sources.list.d\/google.list \\\r\n    && mkdir -p \/usr\/share\/desktop-directories \\\r\n    && apt-get -y update && apt-get install -y google-chrome-stable\r\n# Disable the SUID sandbox so that chrome can launch without being in a privileged container\r\nRUN dpkg-divert --add --rename --divert \/opt\/google\/chrome\/google-chrome.real \/opt\/google\/chrome\/google-chrome \\\r\n    && echo \"#!\/bin\/bash\\nexec \/opt\/google\/chrome\/google-chrome.real --no-sandbox --disable-setuid-sandbox \\\"\\$@\\\"\" > \/opt\/google\/chrome\/google-chrome \\\r\n    && chmod 755 \/opt\/google\/chrome\/google-chrome\r\n\r\n# Chrome Driver\r\nRUN mkdir -p \/opt\/selenium \\\r\n    && curl http:\/\/chromedriver.storage.googleapis.com\/2.45\/chromedriver_linux64.zip -o \/opt\/selenium\/chromedriver_linux64.zip \\\r\n    && cd \/opt\/selenium; unzip \/opt\/selenium\/chromedriver_linux64.zip; rm -rf chromedriver_linux64.zip; ln -fs \/opt\/selenium\/chromedriver \/usr\/local\/bin\/chromedriver;\r\n\r\n# Firefox browser to run the tests\r\nRUN apt-get install -y firefox\r\n\r\n# Gecko Driver\r\nENV GECKODRIVER_VERSION 0.23.0\r\nRUN wget --no-verbose -O \/tmp\/geckodriver.tar.gz https:\/\/github.com\/mozilla\/geckodriver\/releases\/download\/v$GECKODRIVER_VERSION\/geckodriver-v$GECKODRIVER_VERSION-linux64.tar.gz \\\r\n  && rm -rf \/opt\/geckodriver \\\r\n  && tar -C \/opt -zxf \/tmp\/geckodriver.tar.gz \\\r\n  && rm \/tmp\/geckodriver.tar.gz \\\r\n  && mv \/opt\/geckodriver \/opt\/geckodriver-$GECKODRIVER_VERSION \\\r\n  && chmod 755 \/opt\/geckodriver-$GECKODRIVER_VERSION \\\r\n  && ln -fs \/opt\/geckodriver-$GECKODRIVER_VERSION \/usr\/bin\/geckodriver \\\r\n  && ln -fs \/opt\/geckodriver-$GECKODRIVER_VERSION \/usr\/bin\/wires\r\n\r\n# python\r\nRUN apt-get update && apt-get install -y \\\r\n    python \\\r\n    python-setuptools \\\r\n    python-pip\r\n<\/pre>\n<hr>\n<h3>Step 2. Build\/Pull the Docker image:<\/h3>\n<p>You can either build your own image using above Dockerfile or you can directly download the image from our Docker Hub repository.<\/p>\n<p>To build the image using above dockerfile,\u00a0you need to save dockerfile to any directory in your system and use the following command:<\/p>\n<pre lang=\"python\">docker build -t image_name path\/to\/dockerfile<\/pre>\n<p>To directly download it from our <a href=\"https:\/\/hub.docker.com\/r\/qxf2rohand\/qxf2_pom_essentials\/\">Docker Hub repository<\/a>,\u00a0you need to use the following command:<\/p>\n<pre lang=\"python\">docker pull qxf2rohand\/qxf2_pom_essentials<\/pre>\n<hr>\n<h3>Step 3. Creating a container and running Selenium tests:<\/h3>\n<p>We decided to use this image for testing our <a href=\"https:\/\/github.com\/qxf2\/qxf2-page-object-model\">Qxf2&#8217;s open sourced GUI automation framework<\/a>. We named the image as qxf2_pom_essentials. qxf2_pom_essentials image is capable of running any Python based Selenium tests. To run the Selenium tests using this image, you need to go through following steps:<\/p>\n<ol>\n<li>Create a Docker container out of this image and enter into the container using the following command:\n<pre lang=\"python\">docker run -it qxf2rohand\/qxf2_pom_essentials \"\/bin\/bash\"<\/pre>\n<\/li>\n<li>Export display and enable Xvfb using following 2\u00a0commands:\n<pre lang=\"python\">export DISPLAY=:20\r\nXvfb :20 -screen 0 1366x768x16 &<\/pre>\n<\/li>\n<li>Install Selenium using pip\n<pre lang=\"python\">pip install selenium<\/pre>\n<\/li>\n<li>Use any Linux editor you like and add your test inside the container. You can also use the sample Selenium code (selenium_docker.py) given below. This selenium test visits Qxf2 Services website and prints the title.\n<pre lang=\"python\"># contents of selenium_docker.py\r\nfrom selenium import webdriver\r\n\r\ndriver = webdriver.Firefox()\r\ndriver.get(\"http:\/\/www.qxf2.com\")\r\nprint driver.title\r\ndriver.quit()<\/pre>\n<\/li>\n<li>Run the selenium test using the following command:\n<pre lang=\"python\">python selenium_docker.py<\/pre>\n<p>The output will be similar to the screenshot shown below.<br \/>\n<figure id=\"attachment_6590\" aria-describedby=\"caption-attachment-6590\" style=\"width: 382px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2017\/08\/output-of-selenium-docker.png\" data-rel=\"lightbox-image-0\" data-rl_title=\"\" data-rl_caption=\"\" title=\"\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-6590\" src=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2017\/08\/output-of-selenium-docker.png\" alt=\"\" width=\"382\" height=\"40\" srcset=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2017\/08\/output-of-selenium-docker.png 382w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2017\/08\/output-of-selenium-docker-300x31.png 300w\" sizes=\"auto, (max-width: 382px) 100vw, 382px\" \/><\/a><figcaption id=\"caption-attachment-6590\" class=\"wp-caption-text\">Fig. 1 Output of selenium_docker.py<\/figcaption><\/figure><\/li>\n<\/ol>\n<p><strong>Note:<\/strong> The above steps are only to show you how to use our Docker image. At Qxf2 Services, for testing our <a href=\"https:\/\/github.com\/qxf2\/qxf2-page-object-model\">Qxf2&#8217;s Public Page Object Model<\/a> we use another Dockerfile which automatically gets our code from GitHub, setup our requirements, run shell script file to enable Xvfb and run the test. <\/p>\n<hr>\n<p>To know more about how to get your code inside the container and run the test, please stay tuned. We will post about it soon. Until then enjoy running your tests anywhere without thinking about environment set up using this Docker image. Happy testing!<\/p>\n<p><strong>If you are a startup finding it hard to hire technical QA engineers, learn more <a href=\"https:\/\/qxf2.com\/blog\/about-qxf2\/\">about Qxf2 Services<\/a>.<\/strong><\/p>\n<\/hr>\n<script>(function() {\n\twindow.mc4wp = window.mc4wp || {\n\t\tlisteners: [],\n\t\tforms: {\n\t\t\ton: function(evt, cb) {\n\t\t\t\twindow.mc4wp.listeners.push(\n\t\t\t\t\t{\n\t\t\t\t\t\tevent   : evt,\n\t\t\t\t\t\tcallback: cb\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n})();\n<\/script><!-- Mailchimp for WordPress v4.10.1 - https:\/\/wordpress.org\/plugins\/mailchimp-for-wp\/ --><form id=\"mc4wp-form-1\" class=\"mc4wp-form mc4wp-form-6165 mc4wp-form-theme mc4wp-form-theme-blue\" method=\"post\" data-id=\"6165\" data-name=\"Newsletter\" ><div class=\"mc4wp-form-fields\"><div style=\"border:3px; border-style:dashed;border-color:#56d1e1;padding:1.2em;\">\r\n  <h1 style=\"text-align: center; padding-top: 20px; padding-bottom: 20px; color: #592b1b;\">Subscribe to our weekly Newsletter<\/h1>\r\n  <input style=\"margin: auto;\" type=\"email\" name=\"EMAIL\" placeholder=\"Your email address\" required \/>\r\n  <br>\r\n  <p style=\"text-align: center;\">\r\n    <input style=\"background-color: #890c06 !important; border-color: #890c06;\" type=\"submit\" value=\"Sign up\" \/>\r\n    \r\n  <\/p>\r\n  <p style=\"text-align: center;\">\r\n    <a href=\"http:\/\/mailchi.mp\/c9c7b81ddf13\/the-informed-testers-newsletter-20-oct-2017\"><small>View a sample<\/small><\/a>\r\n  <\/p>\r\n  <br>\r\n<\/div><\/div><label style=\"display: none !important;\">Leave this field empty if you're human: <input type=\"text\" name=\"_mc4wp_honeypot\" value=\"\" tabindex=\"-1\" autocomplete=\"off\" \/><\/label><input type=\"hidden\" name=\"_mc4wp_timestamp\" value=\"1775943191\" \/><input type=\"hidden\" name=\"_mc4wp_form_id\" value=\"6165\" \/><input type=\"hidden\" name=\"_mc4wp_form_element_id\" value=\"mc4wp-form-1\" \/><div class=\"mc4wp-response\"><\/div><\/form><!-- \/ Mailchimp for WordPress Plugin -->\n<hr>\n","protected":false},"excerpt":{"rendered":"<p>Sometimes your team members complain about automated tests not working on their computer while you are able to run the automated tests at your end completely fine. We too, at Qxf2, have experienced this issue. Our automated tests run fine at our end but occasionally fail when they run on our colleagues and client machines. Invariably, we trace this sort [&hellip;]<\/p>\n","protected":false},"author":12,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[140,18,30],"tags":[],"class_list":["post-6574","post","type-post","status-publish","format-standard","hentry","category-docker","category-python","category-selenium"],"_links":{"self":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts\/6574","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/users\/12"}],"replies":[{"embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/comments?post=6574"}],"version-history":[{"count":51,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts\/6574\/revisions"}],"predecessor-version":[{"id":12503,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts\/6574\/revisions\/12503"}],"wp:attachment":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/media?parent=6574"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/categories?post=6574"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/tags?post=6574"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}