Site icon Vinsguru

Selenium WebDriver – How To Run Automated Tests Inside A Docker Container – Part 1

Overview:

Testautomationguru already has few docker and selenium related articles which talks about setting up the dockerized selenium grid.

  1. Setting up Dockerized Selenium grid.
  2. Managing Dockerized Selenium Grid using Arquillian cube.
  3. Setting up Dockerized Selenium grid in AWS / Cloud using RancherOS

Even if we have a selenium grid, we still need a host to run our tests – ie.. a host is required to run your maven command/ant/some batch file to execute the tests – so that test could talk to remote grid to send the WebDriver related instruction. In this article, we will see how we could use a container (as a host) for running our tests.

Udemy – Selenium WebDriver With Docker:

TestAutomationGuru has released a brand new course in Udemy on Selenium WebDriver with Docker. 14 hours course which starts with installing docker from scratch and goes all the way up to running dockerized selenium tests on AWS cloud. Please access the above link which gives you the special discount.  You can also get your money back if you do not like the course within 30 days.

Challenges In Test Execution:

We already have simplified our selenium grid set up using docker using the above articles. But we still face few challenges. Your tests still have few dependencies to run them!

Managing these dependencies & Setting up remote slaves are time-consuming for big applications which has thousands of test cases to run on a daily basis on a multiple slave machines.

That too, if you are planning to move AWS /cloud in future, How can you set this up all programmatically?

We will see how docker could help us here!!

Considering the length of the article, I divided this into 2. I would suggest you to read the second part as well. I have attached a sample project in the Part 2.

Sample Test:

To show a demo, I am creating a simple maven project. I add the selenium-java & testNG dependencies.

<dependencies>
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>3.5.2</version>
        </dependency>
        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>6.11</version>
        </dependency>
</dependencies>

I add the below page object.

public class GooglePage {

    private final WebDriver driver;
    private final WebDriverWait wait;

    @FindBy(name = "q")
    private WebElement searchBox;

    @FindBy(css = "input.lsb")
    private WebElement searchButton;

    @FindBy(className = "rc")
    private List<WebElement> searchResults;

    @FindBy(id = "foot")
    private WebElement footer;

    public GooglePage(final WebDriver driver) {
        this.driver = driver;
        PageFactory.initElements(driver, this);
        this.wait = new WebDriverWait(driver, 30);
    }

    public void goTo() {
        this.driver.get("https://www.google.com");
    }

    public void searchFor(String text) throws InterruptedException {
        this.searchBox.sendKeys(text);
        wait.until(ExpectedConditions.elementToBeClickable(this.searchButton));
        this.searchButton.click();
        wait.until(ExpectedConditions.presenceOfElementLocated(By.className("rc")));
    }

    public List<WebElement> getResults() {
        return this.searchResults;
    }

}

A corresponding TestNG Test would be as shown here.

public class GoogleTest {

    private WebDriver driver;
    private GooglePage google;

    @BeforeTest
    public void setUp() throws MalformedURLException {
        DesiredCapabilities dc = DesiredCapabilities.chrome();
        driver = new RemoteWebDriver(new URL("http://my-selenium-grid-ip:4444/wd/hub"), dc);
        google = new GooglePage(driver);
    }

    @Test
    public void googleTest() throws InterruptedException {
        google.goTo();
        google.searchFor("automation");
        Assert.assertTrue(google.getResults().size() >= 10);
    }
    
    @AfterTest
    public void tearDown() throws InterruptedException {
        driver.quit();
    }    

}

Note: I hard code the selenium grid IP details here. No worries. Please continue reading this and the next article. I have explained how to pass parameters to create a complete robust dockerized automated testing!

Now You could simply execute the test,

mvn clean test
java -cp mytest.jar org.testng.TestNG -testclass org.testautomationguru.test.GoogleTest

If I need to execute my tests using Jenkins in a remote slave, I need to ensure that my remote machine also has  java, maven etc. If the test depends on few jar files which are not part of maven repo, We need to ensure that it is copied to the appropriate remote local maven repo.  Basically – you need to set up entire dependencies in each machine for your tests to execute!  A lot of manual work!! This is where Docker is going to help.

Dockerfile Maven Plugin:

Maven has a dockerfile plugin which nicely integrates docker and maven. It automates docker image build process in maven. By issuing a maven command, maven

My project looks like this.

To use the plugin, I add the below dependency in the maven pom file.

<plugin>
    <groupId>com.spotify</groupId>
    <artifactId>dockerfile-maven-plugin</artifactId>
    <version>1.3.5</version>
    <executions>
        <execution>
            <id>default</id>
            <goals>
                <goal>build</goal>
                <goal>push</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <!-- vinsdocker is org name. -->
        <!-- containertest is the name of the image /  application  -->
        <repository>vinsdocker/containertest</repository>
        <!-- version of your image: could be sprint11 or release5 etc -->
        <tag>googletest</tag>
    </configuration>
</plugin>

My Dockerfile is as shown below. My maven creates a single jar (container-test.jar) with all the dependencies by using maven-assemply-plugin.

Dockerfile:

FROM openjdk:8-jre-slim

# Add the jar with all the dependencies
# Maven creates container-test.jar in the target folder of my workspace.
# We need this in some location - say - /usr/share/tag folder of the container
ADD  target/container-test.jar /usr/share/tag/container-test.jar

# Command line to execute the test
ENTRYPOINT ["/usr/bin/java", "-cp", "/usr/share/tag/container-test.jar", "org.testng.TestNG", "-testclass", "com.testautomationguru.container.test.GoogleTest"]

When I issue the below command, maven takes care of building the project and also creates a docker image.

mvn clean package

It builds a new docker image which could be accessible using vinsdocker/containertest.

 


Note:

By default the plugin will try to connect to docker on localhost:2375. If the docker is not running on your machine and you would like to use remote docker, set the DOCKER_HOST environment variable.

DOCKER_HOST=tcp://<host>:2375

Now the docker image has been built with all the dependencies. An entrypoint has also been added – it means whenever you create a container (an instance of the docker image), it starts executing the test.

In my remote slave, I need to issue only below command – docker run vinsdocker/containertest:googletest

sudo docker run vinsdocker/containertest:googletest
Aug 27, 2017 4:06:05 AM org.openqa.selenium.remote.ProtocolHandshake createSession
INFO: Detected dialect: OSS
Browser launched and navigated to Google
automation - entered for search
Search button clicked
Results appeared
Results Count : 11

===============================================
Command line suite
Total tests run: 1, Failures: 0, Skips: 0
===============================================

I explicitly added few comments in the page object for better understanding.

Now we do not need to worry about the dependencies to run the automated test. As everything to run the test is packaged as an image. We need only machines (any OS ) with docker installed!  Issuing below command is enough to run our test in the cloud!! Docker will automatically download the image, creates an instance/container, runs the test and exits!!

docker run vinsdocker/containertest:googletest

I request you NOT to try this right away without reading the Part 2 of this article.

I have uploaded this project in GitHub – Please continue reading the Part 2 of this article to get the Github link.

Summary:

Docker not only helps us in setting up the selenium grid – but also simplifies managing test dependencies. Maven creates a new docker image as part of maven build process by using the given Dockerfile. Once the image is built, any machine with docker can execute the test!  It saves a lot of manual work in setting up the remote slave for execution.

In this approach we hard-code the selenium grid IP which we do NOT want. We want the selenium grid itself to be started at run time. So, We are not yet done!! We can still improve the process. Please continue reading this article – Running Dockerized Selenium Suites – Part 2

 

Happy Testing & Subscribe 🙂

 

Share This:

Exit mobile version