How to Configure Test Environment and Run Selenium Tests Using Docker

April 6th, 2017

QA / Wiki // Oleksandr

Quality assurance is one of the key elements of success and the mark of a good QA engineer is his/her efficiency (that, and attention to details). Thankfully, there are many tools that help QAs. We're going to take a look at running Selenium tests using Docker. 

WHERE DO YOU START?

If you are not familiar with Docker technology, here's a brief overview: 

  • Docker shares Linux kernel of your host machine, which means Docker testing involves fewer resources in the process of running containers. This makes Docker a very lightweight platform. 
  • Docker allows you to run several completely isolated containers at the same time without overloading your system. This makes both development and testing of your project more secure. 
  • Docker allows you to use the same configuration of the environment that uses the production server. This prevents numerous errors and bugs that may be caused by differences in environments.
  • Docker provides a remote repository to store and share images inside the large community of Docker users.
  • Docker images make delivering your application very easy. There's no need to worry about the software differences because all software and its dependencies are included in the Docker image. 
  • Docker makes it easy to split the process of testing into several parallel processes. 
  • Because Docker project is an open-sourced one and there is a large community supporting it. 

The advantages of Docker

  • Speed
  • Lightweight tool
  • Isolation
  • Automation
  • Portability
  • Migration
  • And many other...

CONFIGURING TEST ENVIRONMENT

So now is a time to configure the testing environment. For this, you will need: 

  • Code and config files
  • Browser part (Selenium project provides standalone images for Chrome and Firefox for cross-browser testing)
  • Storage part (there are images for all popular databases)

My stack of the testing environment looks like this: 

Codeception image needs to be improved because the official image does not include the pdo_mysql driver. To solve this problem, I created my own image, which you can find here. 

For simple Selenium tests, I used the next configuration of the functional.yml: 

class_name: FunctionalTester
modules:
    enabled:
        - WebDriver
        - Asserts
        - Helper\FunctionalHelper
    config:
        WebDriver:
            host: firefox
            url: http://yourprojecturl.com
            browser: firefox
            port: 4444
            window_size: 1024x768
            restart: true
env:
    chrome:
         modules:
            config:
                WebDriver:
                    browser: 'chrome'
                    host: chrome
                    window_size: 1440x960
 
    firefox:
        # nothing changed

The best way to configure the running of all images, including the volumes sharing, exposing ports, and setting dependencies, is to use Docker Compose. 

Take a look at the docker-compose.yml and I'll explain what's going on there: 

version: '2'
services:
  codecept:
      image: vicheus/codeception
      depends_on:
        - chrome
        - firefox
        - mysql
      volumes:
          - '/home/developer/projects/erp/htdocs:/project/'
          - '/home/developer/projects/erp/htdocs/codeception.yml:/project/codeception.yml'
          - '/home/developer/projects/erp/htdocs/tests:/project/tests'
  chrome:
      image: 'selenium/standalone-chrome-debug:2.53.1'
      ports:
          - '5900'
      dns: 8.8.4.4
      environment:
        - no_proxy=localhost
  firefox:
      image: 'selenium/standalone-firefox-debug:2.53.1'
      ports:
          - '5900'
      dns: 8.8.4.4
      environment:
        - no_proxy=localhost
  mysql:
      image: mysql/mysql-server:5.5
      environment:
        - MYSQL_ROOT_PASSWORD=root
        - MYSQL_DATABASE=erp
        - MYSQL_USER=root
        - MYSQL_PASSWORD=root

What's going on there:

  • The first line specifies the Docker Compose version that should be used. At the moment, version 3 is the latest one. 
  • In services section, there is the configuration for each container that will be running after the docker-compose up. 
  • Next (Codeception, Docker in Chrome, MySQL) line specifies the hostname of the container. It is similar to docker run -h
  • Image declaration specifies the Docker image that will be used to create the container
  • The line with depends_on defines the connections in the container. In the example shown above, you can see that Codeception container will start only after Chrome and MySQL containers will be started. 
  • In the volumes declaration, you can share volumes on the host machine with the ones inside the Docker container. In my example, I have shared the source code of the project, tests, and the config file of Codeception with the Codeception container. 
  • Ports option gives you a possibility to open container's ports or share them with the host ports. 

As you can see, all the declarations explained above can simply be replaced with Docker engine analogs when you run the container. However, the beauty of the Docker Compose is that you can define all configurations and dependencies between containers in one file and then run all stack in one CLI command: 

docker-compose up -d

And then run tests with another command:

docker-compose run --rm codecept run functional -d --html

Running parallel tests

Docker is helpful for this purpose as well.

First of all, we want to split our tests into groups that we want to execute in parallel. One way to do this is running parallel tests from different directories. Codeception, however, suggests a more flexible approach to resolving this issue - it's called Group. The method is similar to the one used by PHPUnit and behaves in the same way. 

Groups in Codeception can be represented in global or suite configuration files as well as in annotations to specific tests. Annotation version looks like this: 

@group authorization
    public function authorizationTest(\FunctionalTester $I)
    {
        $I->amOnUrl('/login');
        $I->fillField('#username', 'Test');
    }

In your YAML configuration file you can specify test group in a next way:

groups:
        salary: [tests/functional/GroupSalaryOperationCest.php, tests/functional/GroupDeductionOperationCest.php, tests/functional/SingleFinancialOperationCest.php]
        
        order: [tests/functional/OrderCest.php, tests/functional/OrderProductCest.php, tests/functional/OrderInvoiceCest.php]

After that all you need is to run your test with docker-compose:

docker-compose --project-name test-salary run -d --rm codecept run -g salary & \

docker-compose --project-name test-order run -d --rm codecept run  -g order

Conclusions

Docker provides an efficient way to develop, deliver, and run test environment on the different hosts with minimal time costs and knowledge in server administration.

Advantages of using docker as test environment are next:

  • Minimal hardware requirements (if you're using UNIX system)
  • Configure all test environments in one place (docker-compose.yml file)
  • Starting containers & running tests within one CLI command in a few seconds
  • Possibility to split your tests in parallel process that runs simultaneously
  • Painless delivery test environment to the different host machines
  • Possibility to create and run several test environment with its own tests (because of flexible networking system provided by Docker, that allows creating completely isolated systems)
  • Large repository of official images, to create environments with different databases, browsers and even web servers (such as Apache or Nginx)

Need web or mobile software development?

Author: Oleksandr

Oleksandr is one of our senior QA engineers, currently working on a project in the AdTech/MarTech field. His other passions include JavaScript, and frontend development in general.

Tags Development Hacks QA

See all blog

x

Grossum Startup Guide:
Five Things to Consider Before Web & Mobile Development

Get the Guide