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!

  • Test depends on specific version of java (like java 8)
  • Host should have maven or Ant or Gradle or other build tools installed
  • Tests depend on number of 3rd party jar files and other files like csv etc.
  • Tests depend on few jar files which are not part of maven repo!!
  • Remote slaves need to be set up with the build tools, java and any dependent jar files to execute the tests.

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.

container-test-prop

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.

  • A Google Page Object which searches for a string and return search results
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.

  • The test searches for ‘automation’ and checks if the search results count is at least 10.
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,

  • Using maven
mvn clean test
  • Once I have packed them as a jar, I can also execute the test in the command line as shown here
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

  • pulls all the dependencies
  • compiles
  • tests
  • packages all the classes into a single jar with all the dependencies
  • also creates a docker image (based on the docker file)

My project looks like this.

container-proj

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

dockerfile-maven-build

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

container-test-doc-02

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:

53 thoughts on “Selenium WebDriver – How To Run Automated Tests Inside A Docker Container – Part 1

  1. I get an error:
    Error: Main method not found in class com.testautomationguru.container.test.GoogleTest, please define the main method as:
    public static void main(String[] args)
    or a JavaFX application class must extend javafx.application.Application

    dont know what im doing wrong, everything seems ok. Its weird because testng tests doesnt require java main methods

      1. I use now the exactly same POM but it fails:

        First the system gives a warning:
        [WARNING] Artifact: UltimateTest:UltimateTest:jar:0.0.1-SNAPSHOT references the same file as the assembly destination file. Moving it to a temporary location for inclusion.

        Then it crashes:

        Step 2/3 : COPY ./target/UltimateTest-0.0.1-SNAPSHOT.jar ./usr/share/tag/UltimateTest.jar
        [ERROR] COPY failed: stat /var/lib/docker/tmp/docker-builder025734886/target/UltimateTest-0.0.1-SNAPSHOT.jar: no such file or directory

  2. Hello Vinoth,

    I understood till you make a docker image. May I know how you transfer the image to remote slave for docker to execute the image ? I meant to say when u execute docker run command for an image, the docker must have access to the image…. how we handle this ( i am just beginning with docker and try to understand the concept )

    1. Hello Musaffir,
      You can just upload your docker-image to docker online repository and then run or pull your docker image anywhere on your local or remote host.

  3. I got “Error: Could not find or load main class org.testng.TestNG” when executing “sudo docker run vinsdocker/containertest:googletest”, why is that? Thanks

  4. getting this error
    docker run vinsdocker/containertest:demo
    ➜ container docker run vinsdocker/containertest:demo
    java.io.FileNotFoundException: /usr/share/tag (Is a directory)
    at java.io.FileInputStream.open0(Native Method)
    at java.io.FileInputStream.open(FileInputStream.java:195)
    at java.io.FileInputStream.(FileInputStream.java:138)
    at java.io.FileInputStream.(FileInputStream.java:93)
    at or

  5. Hi vlns,

    Great article !!!
    I tried what all you have mentioned and results are encouraging too. Thanks a lot !

    But it fails at the end saying docker image cannot be created , please help !

    11:24:42.488 [main] DEBUG com.spotify.docker.client.DockerCertificates – C:\Users\XXXX.docker\ca.pem, C:\Users\XXXX.docker\key.pem or C:\Users\XXXX.docker\cert.pem does not exist, not using SSL
    [INFO] Building Docker context C:\Users\XXXX\AllureReort\dockerization
    [INFO]
    [INFO] Image will be built as jijotkoshy/dockerization:demo

  6. Hi,

    does ADD command in dockerfile is required???

    Also i am trying to run the docker image and getting below error:
    Error: Could not find or load main class org.testng.TestNG

  7. What is /usr/share/tag/container-test.jar in dockerfile????

    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

    1. I create a directory ‘usr/share/tag’ in the docker image and place all the artifacts inside the location. it can be anything.

  8. Hi,

    I am having issues figuring out how will docker file look in my structure of the project.
    Structure has two regression.xml files and I am not sure what does this signifies – ADD target/container-test.jar /usr/share/tag/container-test.jar
    Sorry I am new to docker

  9. Executing command
    docker run venkydkr/seleniumintegration:googletest

    Output is:

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

    Configuration Failures: 1, Skips: 1

    In test class, i have added url as http://http://localhost:4444/wd/hub. do we need to setup selenium-hub and chrome/firefox node before executing test.

    or If we run docker run venkydkr/seleniumintegration:googletest
    will it take care about hub & node setup?

    While executing this test class how can i see test logs as like
    sudo docker-compose up | grep -e ‘order-module’ -e ‘search-module’

      1. Thank you… I have one more doubt , I am using windows, how to write ENTRY POINT in windows…?? And also I am using cucumber and not TestNG

  10. Hi Vinoth,
    How to write a docker file in windows, here you are writing in mac, i have little confusion how to give path in windows…???

    1. It does not matter if it is windows/mac/linux. You use a base image. You add files from your project directory relative to the Dockerfile to a path in the image. Check Docker site for reference.

  11. Hi Vinoth,
    This is a great series and I encourage readers to continue on with the rest of the posts.

    I do have a question for you regarding Docker / Maven / Jenkinsfile – Pipeline
    After reading your series I found articles about Jenkinsfile – Pipeline and using Docker images within it. I’m wondering if you’ve looked into Jenkins-Pipeline and its Docker related capabilities and what if any of the maven/docker work you would move out of maven and into a Jenkinsfile.

    I’m interested in what your philosophy is on what goes into the pom.xml vs what should be in the Jenkinsfile as I believe you have got quite a bit of experience in making these decisions.
    Thanks,
    TIm

    1. Hi Tim,

      Maven-docker plugin is not CI tool dependent. (and Yes, Jenkinsfile approach does not have maven dependency). In case of Jenkins, It is good to separate ‘building docker image’ process from maven and keep it as a separate stage in the pipeline. This way, users would not be encouraged to push the docker images into the registry without pushing the code to code-repo as maven-docker plugin kind of encourages which does not seem to be a good process.

  12. When i run -sudo docker run vinsdocker/containertest:googletest
    I am gettign error –
    Error: Could not find or load main class org.testng.TestNG

    My docker file –

    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/test-0.0.1-SNAPSHOT.jar /usr/share/tag/test-0.0.1-SNAPSHOT.jar

    Command line to execute the test

    ENTRYPOINT [“/usr/bin/java”, “-cp”, “/usr/share/tag/test-0.0.1-SNAPSHOT.jar”, “org.testng.TestNG”, “-testclass”, “test.test.Testing”]

  13. If I may ask. You have used Javascript as the programming language for the tests. Could you please let me know the IDE that you have used. Or some links to build a MAVEN javascript project for IDE’s except eclipse. Like VSCode or the sorts.

  14. Hey vIns, one thing is not very clear to me in terms of the benefits…
    Once you package the project on a .jar doesn’t it already takes care of the dependencies and whatnot?
    The way I see it these 2 steps you listed –
    “Tests depend on number of 3rd party jar files and other files like csv etc.
    Tests depend on few jar files which are not part of maven repo!!” –
    would’ve been taken care of by the .jar so all you would need on the slave machines would be maven and java installed, right?
    I might’ve understood the maven packaging system wrong tho, could you clarify that?
    Thanks, very good article!

    1. Hi, the benefits could depend on your project & how you run your tests etc. for ex: if you run your automated tests by pulling the code from source control and issue ‘mvn clean test’ & assuming all the resources are part of your project, then you might think that the remote machine just needs maven and java. if you do that way, all the jars might not be available in the maven repo. In that case you might have to manually move the jar to your local repo using few commands to use them in your project. you need to do the same in the remote machine as well. If you move to cloud – for test execution, if you launch/terminate instances at will, then we need to setup slave machine every time, rt?

      As you package jar with all the class files you need, Docker packages the complete run time environment – so that it runs on any hardware in the cloud.

  15. I am still getting an error. Exception in thread “main” org.testng.TestNGException:
    Cannot load class from file: com.testautomationguru.container.test.GoogleTest
    at org.testng.internal.ClassHelper.fileToClass(ClassHelper.java:551)
    at org.testng.TestNG.configure(TestNG.java:1383)
    at org.testng.TestNG.privateMain(TestNG.java:1344)
    at org.testng.TestNG.main(TestNG.java:1323).
    I have used below 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
    ADD target/libs /usr/share/tag/libs

    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”]

    I have used same POM file as inhttps://github.com/vinsguru/docker-selenium-test except the tag is GoogleTest instead demo for docker images. Please help

    1. Lets do one step at a time. Can you just simply clone the project and try to build in your local without modifying anything.? if that works, lets keep changing other things one by one. if you change demo to GoogleTest, it should not be a problem at all. But i would like to see whats going on. so start from just cloning a fresh project

  16. Hi Vins

    It is a great article. I learnt lot of new things.

    I am getting following error when I try to buil on my windows local(have docker) without modifying any thing after cloning project.

  17. While running docker run command , i m getting “docker: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?.
    See ‘docker run –help’.”

  18. Hi,

    Instead of running a single test class, I need to run a full test suite mentioned in testng.xml. How can I achieve that? Please help.

  19. HI ,

    Thanks for the post. If i provide my test data as a part of my framework in an excel will the docker container recognize the files and execute? Kindly tell me your experience ….

Leave a Reply to Mephisto Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.