Don’t use assertTrue to verify a text
March 13, 2020Testing is like…
June 22, 2020Introduction
You might want to run a test that is hosted on GitLab. Instead of clone, build, and run the tests locally you would like to do it on a CI/CD application. Thankfully GitLab has the GitLab CI, where you can use it to run your pipeline.
Wherever you want to use: demonstrate a pipeline execution during a presentation, test your open source project and other things you need, you can use only one platform like GitLab.
Step 1: remember it’s headless
Why?
Most of the steps on a pipeline are done inside a container that does not have a GUI (Graphical User Interface), so you need to consider this.
When we run automated web tests we need a web browser like Google Chrome or Firefox. When we run the tests locally using Selenium WebDriver in any programming language it opens the browser and does the actions inside our test script.
How to
Let’s talk about the code that you can execute locally first and, later on, run in the pipeline.
You must “tell” your browser that you want to run the tests on it in headless mode. I’m going to use Google Chrome for this.
The Selenium WebDriver Java library has the class ChromeOptions
, where you can “tell” the browser the configurations you would like to do. We need to add the ability to execute the tests in the headless mode, so we can use:
ChromeOptions options = new ChromeOptions();
options.setHeadless(true)
We must tell the ChromeDriver that we need to use this headless option, so we need to pass it as a parameter for the ChromeDriver class during the object creation. Take a look at the code snippet below:
@BeforeAll
static void webdrivermanagerSetup() {
WebDriverManager.chromedriver().setup();
ChromeOptions options = new ChromeOptions();
options.setHeadless(true);
driver = new ChromeDriver(options);
driver.get("https://github.com/bonigarcia/webdrivermanager");
}
On line 3 we have the Chrome driver setup using the WebDriverManager, so we don’t need to be worried about configuring manually the driver.
On line 5 have the creation of the ChromeOptions
object, and setting the headless mode on line 6.
On line 8 we are creating the browser instance, passing the options as a parameter for the browser.
On line 10 we are accessing a page.
Now we have the browser set with the headless mode.
Step 2: running into a container
Why?
If you need to run your tests inside the GitLab CI a container with Java JDK, Maven, and Google Chrome is necessary. A container that has all of this is necessary, so we need to find one.
If you try to run your web tests directly into a container without the web browser, in our case Google Chrome, you will face this issue:
root/.m2/repository/webdriver/chromedriver/linux64/83.0.4103.39/chromedriver: error while loading shared libraries: libX11.so.6: cannot open shared object file: No such file or directory
This part “libX11.so.6: cannot open shared object file” tells us that we are trying to run something with a GIU, but no user interface or library (like X11 / Xvfb) was not found.
A detailed log error can be found here: https://gitlab.com/elias.nogueira/webdrivermanager-pipeline-test/-/jobs/581828359
Now we know that we need a container with an emulated GIU interface (X11).
How to
We need to build or find a docker image we can use. I will use an existing one to make it easy to add and run for now.
One good thing about the GitLab CI is the ability to get open docker images on the Docker Hub. If you search all the tools we need on a container you might find this one: docker-maven-chrome.
Now it’s time to create the .gitlab-ci.yml
file and use the docker image mentioned, so the image on the GitLab CI file will be:
image: markhobson/maven-chrome:jdk-11
The complete .gitlab-ci.yml
file will be explained in the next session.
Step 3: create your pipeline
Why?
When you need to execute something, like we want to run out web tests hosted on GitLab, you must define the steps to be executed.
You can find a lot of materials and good practices about how to create the pipeline steps but, to make it clear and easy to follow, I will have only two steps: build and test.
So the build step will compile the code and download the necessary libraries and the test step will execute the tests.
How to
Take a look at this pipeline:
image: markhobson/maven-chrome:jdk-11
stages:
– build
– test
variables:
MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository"
cache:
paths:
– .m2/repository/
– target/
build:
stage: build
script:
– mvn compile
test:
stage: test
script:
– mvn test -Dtest=com.eliasnogueira.wdm.GithubWDMPageTest
On line 1 we are using the docker image that has Java JDK 11, Maven, and Google Chrome.
On lines 3 to 5 we are defining the stages of the pipeline: build and test.
On lines 7 and 8 we are defining the local maven repository.
On lines 10 to 13, we are telling GitLab CI to cache the maven repo and the target folder. It will make the process faster after the first execution because all the necessary libraries and classes will be already there.
On lines 15 to 18, we are defining the build step running mvn compile
as the command to build it. You might use another maven lifecycle, but this one works ok for this purpose.
On lines 20 to 23, we are defining the test step running the tests via mvn test
, and adding as a property (-D
) the test class we want to run.
Final step: create your code, or use my example
This post showed you how to run your Selenium WebDriver tests using the GitLab CI with a docker image that contains Google Chrome inside it.
Now, instead of running the tests locally, you can run them using a pipeline and make sure your code works anytime running it manually or during each pull request.
In short, the process is easy:
- Find (or build) a docker image with Java JDK, Maven, and Google Chrome (or another browser you want)
- Add the headless capability for your browser
- Create the pipeline script (
.gitlab-ci.yml
) adding the custom docker image and the steps you want to execute
You can find a complete working project at https://gitlab.com/elias.nogueira/webdrivermanager-pipeline-test
BONUS: Using your docker image on GitLab CI
You can use the GitLab Container Registry to deploy your custom docker image and use it in the pipeline.
I’ve created, in the same project example, a branch called gitlab-registry that has only two differences compared to the code in the master branch:
- A
Dokerfile
that is based onmaven:3.6.3-jdk-11
image that installs Google Chrome. Click here to see the file. - An image update
.gitlab-ci.yml
using the custom image deployed on the GitLab Container Registry. Click here to see the file.
More details about this approach can be found in the README file for the mentioned branch.
18 Comments
This is superb. Thanks for sharing. I am finding the gitlab solution from many days.
Awesome, I’m glad it was useful for you!
Useful one, thank ou.
This is really helpful! Thanks a lot!
However I have a question. I believe if we are using Actions Class to move to an element and the perform an interaction(click, drag and drop, etc), will it still work in headless mode? Is there a way we can run the non-headless version inside the container?
Thanks again
Hi Robert!
You are right! The Actions class works with the headless mode. The tricky part is that, sometimes, you might fail due to an
org.openqa.selenium.WebDriverException: Element is not clickable at the point
. It happens because the element is not “visible” on the screen, given the viewport. So, to solve this you can increase the screen resolution.There’s a container called elgalu where you can see that the browser is doing through a VNC connection.
Thanks!
Its working properly for the normal test cases. But i have test which connected to web url in that case its not working and its throwing a Connection_refused exception. any idea about the issue.
Hi Arjun,
I think you should only the connection refused if the pod/container cannot find the URL.
Did you try to hit an internal URL that’s behind a proxy?
sir
very informative article thanks you.
I have one doubt. Can we use testng instead of junit to run tests? if so please guide me how we can do?
Hi Rakesh,
Actually, you just need to remove the JUnit library and add TesNG as a new dependency.
Then re-import the @Test and that’s it.
It’s simple and helpful example to run selenium tests in GitLab CI. I am searching for sample project and found your shared project which is clear with details steps explanation. Will follow the instructions and sample code to run our automation scripts from GitLab CI. Thanks a lot for sharing. Pls keep posting it is really very helpful to the learners/explorers like me. 🙂
Thank for sharing!
Can you dockerize your selenium maven then test in gitlab CI with one app running in docker container?
Hi,
If you would like to do it all together (the project, the browser, and the test execution) it’s possible, and the .gitlab-cy.yml file on the repo shows that.
If you want to have it separately I would recommend not dockerize the test project, as you need to run it (maybe) multiple times in different targets (browsers, configurations, etc.)
The following project has one example using the Zalenium approach https://github.com/eliasnogueira/selenium-java-lean-test-achitecture
HI, java.awt.HeadlessException:
No X11 DISPLAY variable was set, but this program performed an operation that requires it. how i set up X11 DISPLAY variable. Also, how do I run database tests with CICD?
Hi Dil,
Could you give me more examples of what do you want to achieve?
I will able to help you if you provide me more information about it.
Best!
Hi Elias the content is very useful but I have one query that how we can use selenium in an webapp projects means how we can test the code in gitlab of maven webapp project??
Where we need to define the script for test??
Hi Manish,
It depends on how do you want to run the project on a web app. If it’s about adding the test in the same web app project and running it you might need to change the command to run the tests, using the automation tool that supports it.
Examples: if your web app is made using Javascript you might use a JS web test automation tool. If you do want to use Selenium WebDriver with Java for a JS web app you might need to somehow trigger the test from a separate project. It’s called Multi Pipeline: https://docs.gitlab.com/ee/ci/pipelines/multi_project_pipelines.html
ELias, thanks a lot for the great content that you regularly share.
I am little bit confused because this example has to do with WebDriverManager, but in the images you use the chrome driver is also installed(apart from the browser). I guess that Chrome driver installation and initialisation is going to be handled by the WebDriverManager, right?
Thanks a lot for your time.
Hello!
You are right, the Docker image already have the Chrome driver, but a fixed version for that: 91 and the necessary version will be handled by the WebDriverManager.
For example: let’s say you update the Chrome browser in the Docker image. The WebDriverManager will detect its version and will download the proper related chrome driver version.
Thank you for your question!
Happy tests!