Search code examples
dockerseleniumdocker-composecucumberselenium-grid

selenium grid/cucumber and docker compose: run a parallel test on several nodes


In order to train myself in the technologies mentioned above, I created a project with a single test that checks a user’s navigation on the home page of the stackoverflow site.

The hub and the 3 nodes of the selenium grid appear to be correctly configured The test runs correctly and I would now like to run this test simultaneously on several browsers.

I wrote my test like this: cucumber:

Feature: search the home page of stackoverflow

  Scenario: Go to the site stackoverflow
    Given I'm on google search page
    When I enter the name of the site
    Then I'm navigated on the home page of stackoverflow

Selenium:

public class StepGoStackoverflowChrome {
    RemoteWebDriver driver;
    String nodeUrl;

    @Given("I'm on google search page")
    public void i_m_on_google_search_page() {
        try {
            nodeUrl = "http://localhost:4444";

            ChromeOptions options = new ChromeOptions();
            // options.addArguments("--headless");
            options.addArguments("start-maximized");

            driver = new RemoteWebDriver(new URL(nodeUrl), options);
            driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
            driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);
            driver.get("https://www.google.com");
        } catch (MalformedURLException error) {
            error.printStackTrace();
        }
    }

    @When("I enter the name of the site")
    public void i_enter_the_name_of_the_site() {
        WebElement webElementList = driver.findElement(By.id("L2AGLb"));
        webElementList.click();
        driver.findElement(By.name("q")).sendKeys("stackoverflow", Keys.ENTER);
    }

    @Then("I'm navigated on the home page of stackoverflow")
    public void i_m_navigated_on_the_home_page_of_stackoverflow() {
        driver.findElement(By.xpath("//a[@href='https://stackoverflow.com/']")).click();
        driver.close();
    }
}

and finally the docker file consists that launches 3 containers with images of web drivers chrome, firefox and edge:

version: "3"
services:
  chrome:
    image: selenium/node-chrome:4.1.1-20211217
    shm_size: 2gb
    depends_on:
      - selenium-hub
    environment:
      - SE_EVENT_BUS_HOST=selenium-hub
      - SE_EVENT_BUS_PUBLISH_PORT=4442
      - SE_EVENT_BUS_SUBSCRIBE_PORT=4443
      - SE_NODE_MAX_SESSIONS=2

  edge:
    image: selenium/node-edge:4.1.1-20211217
    shm_size: 2gb
    depends_on:
      - selenium-hub
    environment:
      - SE_EVENT_BUS_HOST=selenium-hub
      - SE_EVENT_BUS_PUBLISH_PORT=4442
      - SE_EVENT_BUS_SUBSCRIBE_PORT=4443
      - SE_NODE_MAX_SESSIONS=3

  firefox:
    image: selenium/node-firefox:4.1.1-20211217
    shm_size: 2gb
    depends_on:
      - selenium-hub
    environment:
      - SE_EVENT_BUS_HOST=selenium-hub
      - SE_EVENT_BUS_PUBLISH_PORT=4442
      - SE_EVENT_BUS_SUBSCRIBE_PORT=4443
      - SE_NODE_MAX_SESSIONS=3

  selenium-hub:
    image: selenium/hub:4.1.1-20211217
    container_name: selenium-hub
    ports:
      - "4442:4442"
      - "4443:4443"
      - "4444:4444"

I finally run the docker composes with the command:

docker-compose -f docker-compose.yml up

I duplicated the test class by modifying the use of ChromeOptions by FireFoxOption and InterneExplorerOptions in the hope that the tests would start, but I had doubts. This gives the following error:

Exception in thread "main" io.cucumber.core.exception.CucumberException: 

    io.cucumber.core.runner.DuplicateStepDefinitionException: Duplicate step definitions in com.seleniumtest.formation.demo.cucumber.steps.StepGoStackoverflowChrome.i_m_on_google_search_page() and com.seleniumtest.formation.demo.cucumber.steps.StepGoStackoverflowFirefox.i_m_on_google_search_page()

I understand that this creates a language ambiguity in the definition of the test steps with cucumber. Do you have tutorials or ideas for me to consider. Thank you


Solution

  • I achieved a similar thing with the help of Java + testng + cucumber. testng.xml with 3 <test> tags with <parameter> and run tests in parallel. For.eg.,

    <suite name="parallel" parallel="tests" thread-count="5">
      <test name="chrome>
        <parameter name="browser" value="chrome"/>
        <classes>
          <class name="YOUR.CLASS.PATH"/>
        </classes>
      </test>
      <test name="firefox>
        <parameter name="browser" value="firefox"/>
        <classes>
          <class name="YOUR.CLASS.PATH"/>
        </classes>
      </test>
      <test name="edge>
        <parameter name="browser" value="edge"/>
        <classes>
          <class name="YOUR.CLASS.PATH"/>
        </classes>
      </test>
    

    and based on the value of browser you can set the capabilities

    @Parameter("browser")
    @BeforeMethod
    public void beforeMethod(String browser) {
      if (browser.equals("chrome))
         // driver for chrome
      // and so on
    }