Test Automation with Selenide: Run Selenoid with Docker Compose file
Selenide and Selenoid are popular test frameworks with great capabilities you just need to explore for reducing time spent on typical bugs and have business logic in a focus. Running Selenoid with Docker Compose file adds even more advantages to the whole process.
We’ll take some basic Selenide project with TestNG, check its core features, learn how to connect our project with Selenoid, and run it with Docker Compose file. That will be simple, the only a few steps to follow.
Written by Nazar Masliy
1.Selenide + TestNG + Maven
To build and manage our project we’ll use Maven, therefore we need to configure our pom.xml file. The main dependencies and a compilation plugin with properties for Maven to compile sources of the project — check below. We chose TestNG as a testing framework.
Pom.xml
<groupId>selenoid-test.com</groupId>
<artifactId>selenoid-test.com</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.codeborne</groupId>
<artifactId>selenide</artifactId>
<version>5.14.2</version>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>7.1.0</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
2. Page Object classes
Now we can start to create our page objects. There are two classes below. Main Page class describes the main page of https://www.wikipedia.org/ and Result Page class describes page with search results.
Check the main locators:
The first — searchField is defined by ID, the second — searchButton, defined by xpath.
The typeSearchData() checks if searchField is visible, sets a value to this field, and, in the end, returns the current object this.
The second method searchData() responsible for clicking on searchButton and, as a result, it returns ResultPage. Returning current page objects or new page objects allows us to use chaining in test classes.
Main Page
public class MainPage {private SelenideElement searchField = $(By.id("searchInput"));
private SelenideElement searchButton = $x("//*[@id='search-form']//button");public MainPage typeSearchData(String data) {
searchField.shouldBe(visible);
searchField.setValue(data);
return this;
}public ResultPage searchData() {
searchButton.shouldBe(visible).click();
return new ResultPage();
}}
On the Result page Selenide element is defined with ID locator for the Result page header. It responds to search data and, also, define a getter for this element.
Result Page
public class ResultPage {private SelenideElement header = $(By.id("firstHeading"));public SelenideElement getHeader() {
return header;
}
}
3. Test class creation
Test class represents a simple test: open the Main page, search data, go to the Result page, check the Result page header.
WikiTest
public class WikiTest {@BeforeClass
public void setUp() {
baseUrl = "https://www.wikipedia.org/";
browser = "chrome";
}@Test
public void CheckSearch() {
MainPage mainPage = new MainPage();
Selenide.open(baseUrl);
SelenideElement header = mainPage.typeSearchData("test").searchData().getHeader();
header.shouldBe(visible);
String headText = header.getText();
Assert.assertEquals(headText, "Test");
}
}
4. Docker and its advantages
Docker is a tool based on OS-virtualization for delivering software products in packages, named containers.
The chief Docker’s advantages refer to:
- Convenient isolation of application.
- Consistency.
- Scalability.
- Maintainability.
- Clean monitoring.
Speaking about Docker, we should also define its main objects:
- Images — snapshots and read-only templates with instructions on Docker container creation.
- Containers — runnable instances of the image.
- Services — tools, allows you to scale containers.
5. Docker installation
For installing Docker use the next command on Ubuntu:
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add — && sudo add-apt-repository “deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable” && sudo apt install docker
Also, you have to install Docker Compose tool:
$ sudo curl-L “https://github.com/docker/compose/releases/download/1.27.4/docker-compose-$(uname -s)-$(uname -m)” -o /usr/local/bin/docker-compose && sudo chmod +x /usr/local/bin/docker-compose
For MacOS and Windows go to https://hub.docker.com/, register and download Docker desktop application.
6. Selenoid and its advantages
Selenoid is a server that allows running isolated browsers in a Docker container.
Advantages:
- Fast and simple installation.
- Resources consumption and utilization.
- Isolated environment.
- Multiple browsers version support.
- UI and logs.
7. Compose file creation
We’ll optimize Selenoid installation with the help of the Docker Compose file.
Below you can see the Compose file in the 3rd version. It includes the next services: Selenoid, Selenoid-UI, and Chrome_79. In the Compose file, you can notice a network named “Selenoid”. It should be created before running the Compose file. To do it, use the following command: docker network create selenoid.
More detailed information about the creation of the Docker Compose file you can find here: https://docs.docker.com/compose/gettingstarted/
Compose file
version: '3'
services:
selenoid:
image: "aerokube/selenoid:latest"
container_name: selenoid
ports:
- "4445:4444"
networks:
- selenoid
volumes:
- ".:/etc/selenoid"
- "./target:/output"
- "/var/run/docker.sock:/var/run/docker.sock"
- "./target:/opt/selenoid/video"
environment:
- "OVERRIDE_VIDEO_OUTPUT_DIR=$PWD/target"
command: ["-conf", "/etc/selenoid/browsers.json", "-video-output-dir", "/opt/selenoid/video", "-container-network", "selenoid"]
selenoid-ui:
image: "aerokube/selenoid-ui:latest"
container_name: selenoid-ui
links:
- selenoid
ports:
- "8083:8080"
networks:
- selenoid
command: ["--selenoid-uri", "http://selenoid:4444"]
chrome_79.0:
image: "selenoid/vnc:chrome_79.0"
container_name: chrome_79.0
links:
- selenoid
- selenoid-ui
depends_on:
- selenoid
- selenoid-ui
networks:
- selenoid
volumes:
- "/dev/shm:/dev/shm"
networks:
selenoid:
external:
name: selenoid
Selenoid service is the main hub and based on Selenoid image.
Selenoid-UI is a user interface for tracking logs and changes during test execution.
Chrome service based on Chrome image with version 79.0.
As I`ve explained earlier, all containers in Docker are isolated from each other. Concerning this, for communication among different containers and outside Docker’s ecosystem, we should set outer and inner ports. Outer port — 4445 in Selenoid is applied for access to Selenoid Docker container with inner hub port 4444. Outer port 8083 in Selenoid-UI is used for access to Docker Selenoid-UI container with inner port 8080 and check test execution in a browser.
Also, don`t forget to add browsers.json file with Chrome configuration in the project folder:
{
"chrome": {
"default": "latest",
"versions": {
"79.0": {
"image": "selenoid/vnc:chrome_79.0",
"port": "4444"
}
}
}
}
8. Set capabilities for the test
Let’s modify a bit @BeforeClass setUp method and add Selenoid configurations:
@BeforeClass
public void setUp() {
final DesiredCapabilities capabilities = new DesiredCapabilities();
baseUrl = "https://www.wikipedia.org/";
remote ="http://localhost:4445/wd/hub";
browser = "chrome";
browserVersion = "79.0";
browserCapabilities = capabilities;
capabilities.setCapability("enableVNC", true);
capabilities.setCapability("enableVideo", false);
System.setProperty("selenide.browser", "chrome");
startMaximized = true;
browserSize = "1920x1080";
}
To start Selenoid — open the terminal, go to the project’s directory, run the command docker-compose up, wait till Selenoid services will start. Now, it’s time to execute your tests.
Hints and tricks
From first sight, it may look easy to configure Java Automation Test framework with TestNG, set remote hub, and run tests. But there are some hidden obstacles you can meet.
- When dealing with Docker, it’s a bit difficult to understand, how to launch environments in containers. There are a lot of commands and volumes to run each one separately. Moreover, every container has its own inner and outer port, that could be confusing. With the Docker Compose file all you need — is to set the required containers’ parameters and use one command for launching.
Put all these parameters in the Docker Compose file and just write docker-compose up in the console instead of:
docker run -d --name selenoid \
-p 4445:4444 \
-v /etc/selenoid:/etc/selenoid:ro \
-v /var/run/docker.sock:/var/run/docker.sock \
aerokube/selenoid:1.3.2
- The real difficulties may occur with the right configuring of the Docker Compose file. In this case, make sure, that all ports respond to ports set in the remote configuration of the setUp method. It’s important to pay attention to volumes and not to forget about your Docker network creation.
Recap
Employing Selenide +Selenoid with Docker Compose file is a cost and time-effective solution. I use this approach to my project, and it helps me to reach more profitable results. Speaking from my own experience, the performance became flexible, accurate, and much faster. The Docker compose file makes it possible to run only one command instead of several, so I have more time for optimization and getting top-quality in short terms.
I hope, this article was a helpful read for you. Have questions or some stuff to discuss? Don’t hesitate to drop me a line in the comments.
Stay tuned for what’s new, follow us!