How to run C# tests using Selenium dynamic grid inside GitLab
c# | autotests | selenium | GitLab | tutorial | en
Here is how you can start C# tests in GitLab environment using Selenium Dynamic Grid feature.
Gitlab yml
It all starts with gitlab-ci.yml
since we want to run tests in GitLab.
This yml
starts Docker compose on every commit. That is it.
Here is the gitlab-ci.yml
:
image: docker:latest
variables:
OBJECTS_DIRECTORY: 'obj'
NUGET_PACKAGES_DIRECTORY: '.nuget'
SOURCE_CODE_PATH: '*/*/'
services:
- docker:dind
test:
services:
- docker:dind
stage: test
before_script:
- echo "Before script"
- docker-compose up -d --build
script:
- echo "Script"
- docker-compose exec -w /solution tests dotnet restore SeleniumExample.sln
- docker-compose exec -w /solution tests dotnet build SeleniumExample.sln --no-restore
- docker-compose exec -w /solution tests dotnet test Tests/Tests.csproj --settings Tests/grid.runsettings --logger "console;verbosity=detailed"
allow_failure: false
after_script:
- echo "After script"
- docker-compose down
rules:
- when: always
Docker compose
However, all magic happens in docker-compose.yml
.
version: "3"
services:
selenium-hub:
image: selenium/hub:4.5.0
container_name: selenium-hub
environment:
- SE_NODE_MAX_SESSIONS=10
ports:
- "4442:4442"
- "4443:4443"
- "4444:4444"
node-docker:
image: selenium/node-docker:4.5.0
container_name: selenium-node
volumes:
- ./assets:/opt/selenium/assets
- ./config.toml:/opt/bin/config.toml
- /var/run/docker.sock:/var/run/docker.sock
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_GRID_URL=http://localhost:4444/
tests:
image: mcr.microsoft.com/dotnet/sdk:6.0
container_name: tests
depends_on:
- selenium-hub
- node-docker
volumes:
- .:/solution
tty: true
This compose file starts several containers:
-
selenium-hub
- Selenium hub, comes with UI. -
selenium-node
- this one just spawns new docker containers based on our tests requirements -
tests
- container that used just to run tests inside docker network. I found that it is easier to create dummy container, map whole folder inside of it and use it for execution.tty: true
- here is just a hack so that container won’t be killed before tests started there(normally containers are killed if they have nothing to do).
Settings files
In grid.runsettings
- this is where you would specify test related parameters that may depend on environment where tests are running:
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
<TestRunParameters>
<Parameter name="driver" value="grid" />
<Parameter name="grid_url" value="http://selenium-hub:4444/" />
</TestRunParameters>
</RunSettings>
Then we have config.toml
. This file is just determines mapping between browser and which container should be created by selenium-node
. Later hub will run tests on contaners specified here.
[docker]
# Configs have a mapping between the Docker image to use and the capabilities that need to be matched to
# start a container with the given image.
configs = [
"selenium/standalone-firefox:4.9.1-20230508", '{"browserName": "firefox"}',
"selenium/standalone-chrome:4.9.1-20230508", '{"browserName": "chrome"}',
"selenium/standalone-edge:4.9.1-20230508", '{"browserName": "MicrosoftEdge"}'
]
# URL for connecting to the docker daemon
# Most simple approach, leave it as http://127.0.0.1:2375, and mount /var/run/docker.sock.
# 127.0.0.1 is used because internally the container uses socat when /var/run/docker.sock is mounted
# If var/run/docker.sock is not mounted:
# Windows: make sure Docker Desktop exposes the daemon via tcp, and use http://host.docker.internal:2375.
# macOS: install socat and run the following command, socat -4 TCP-LISTEN:2375,fork UNIX-CONNECT:/var/run/docker.sock,
# then use http://host.docker.internal:2375.
# Linux: varies from machine to machine, please mount /var/run/docker.sock. If this does not work, please create an issue.
url = "http://127.0.0.1:2375"
# Docker image used for video recording
video-image = "selenium/video:ffmpeg-4.3.1-20230508"
# Uncomment the following section if you are running the node on a separate VM
# Fill out the placeholders with appropriate values
#[server]
#host = <ip-from-node-machine>
#port = <port-from-node-machine>
And done!
Local envirionment test execution
During development on your local machine you don’t need to run all of those containers(but you can!) and you can run tests from CLI or from IDE of choice, for this you just need 2 things:
- Make sure you have
testsettings
for your local development - Make sure that your test automation framework can distinguish by those
testsettings
whether it runs locally or in CI environment and use version or driver that you need(ChromeDriver
for local runs vsRemoteWebDriver
for runs in Grid in CI).
runsettings
for you local runs can look like this:
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
<TestRunParameters>
<Parameter name="driver" value="chrome" />
<Parameter name="grid_url" value="" />
</TestRunParameters>
</RunSettings>
Playwright
This also possibe to setup this using Playwright(it also uses Selenium Grid), but talking from expirience some of the browser container versions don’t play nice with some Playwright versions, so you have to mix and match to make tests run.
Links
Dynamic Gird GitHub Selenium docs This article helped a lot, I’ve just adapted this to work in GitLab.