Automated web application testing with PHP, Selenium and GitLab

Mar 19, 2021 by Thibault Debatty | 3567 views

PHP GitLab

The easiest way to test that a web application is working correctly is to use a browser and manually go through the pages. If one wants to automate the testing process, there are conceptually two possible approaches: 1) using raw HTTP requests to simulate a browser or 2) using some library and code to drive an actual browser.

The first approach is used by tools like Symfony BrowserKit and Laravel BrowserKit Testing. It is usually light and fast but, as there is no real browser involved, it is not possible to test the execution of javascript or the result of CSS code.

The second approach is possible thanks to tools like Selenium. It allows to test the entire website, including javascript code, but is generally slower.

In this blog post we will show how to use Selenium with PHP code, and how to integrate with GitLab.


The core component is the Selenium Server, a java server that allows to drive a real instance of a browser. The server supports most current browsers: Firefox, Chrome, Edge, Safari... It is generally accessible through port 4444.

The Remote WebDriver is the client part. It is a library that makes it easy to connect to the Selenium Server and drive the browser. The Remote WebDriver is implemented for various programming languages (PHP, Java, Python, Ruby, C#...).

The combination of the Remote WebDriver and the Selenium Server allows to run the client code on one machine, and the browser on another. It is thus possible to run the PHP test code on a Linux machine, to drive Safari installed on a Mac.

The selenium server can be installed manually, but the easiest way is to run a Docker container that contains the server and a web browser. Here is an example to run selenium with the Chrome browser:

docker run -d -p 4444:4444 --shm-size 2g selenium/standalone-chrome:3.141.59-20210311


Once the Selenium container is running, we can use PHP code to drive the Chrome browser.

First, we must install the Remote WebDriver library:

composer require php-webdriver/webdriver

And now we can use Selenium and Chrome:

// selenium.php
require_once __DIR__ . "/vendor/autoload.php";

use FacebookWebDriverRemoteDesiredCapabilities;
use FacebookWebDriverRemoteRemoteWebDriver;
use FacebookWebDriverWebDriverBy;

// we try to read Selenium URL from environment
// will be used when testing in GitLab
// ideally, we should use PHP dotenv
$selenium_url = getenv("SELENIUM_URL");
if ($selenium_url === false) {
    $selenium_url = "http://localhost:4444/wd/hub";

$capabilities = DesiredCapabilities::chrome();
$browser = RemoteWebDriver::create(

// browse a URL
echo $browser->getTitle() . "

// take a screenshot of the page

// find an element on the page and check content
$el1 = $browser->findElement(WebDriverBy::name("q"));
$el1 = $browser->findElement(WebDriverBy::className("container-fluid"));
echo $el1->getText() . "

// find a form field and interact
$el2 = $browser->findElement(WebDriverBy::name("q"));


Typically, you will want to find an element on the page. The WebDryverBy class provides static methods to find by:

  • id($id)
  • className($class)
  • cssSelector($selector)
  • tagName($tag)
  • linkText($text) or partialLinkText($text) (for links)
  • xpath($xpath)

Once the element is found, you can using following methods to check the element or interact:

  • getText()
  • getId()
  • isDisplayed()
  • click()
  • sendKeys($keys) and submit()


We can also use the Selenium container as a GitLab service, to run our tests at each push. Here is an example gitlab-ci.yml, with 2 jobs for testing against Chrome and Firefox:

  image: cylab/php73
    - selenium/standalone-chrome:3.141.59-20210311
    - composer install
    - SELENIUM_URL="http://selenium-standalone-chrome:4444/wd/hub" php selenium.php

  image: cylab/php73
    - selenium/standalone-firefox
    - composer install
    - SELENIUM_URL="http://selenium-standalone-firefox:4444/wd/hub" php selenium.php

In a real setup, this should take place as the last stage of your pipeline, after unit testing and deployment to the test environment...

This blog post is licensed under CC BY-SA 4.0

Fully customizable emails using Laravel 9
With the release of Laravel 9, the Swift Mailer (that is no longer maintained) has been replaced by the Symfony Mailer. You can already find some useful information about this change along all the other ones in the Upgrade Guide from Laravel 8.x to 9.0. However this guide does not contain enough information if you want to send fully customized emails. This blog post proposes you a solution coming directly from the Symfony documentation!
SQL injection with SQLMap
Code injection is one of the most critical web application vulnerabilities. Indeed, the consequences of code injection can be dramatic (impact). Moreover, still today a lot of web applications are vulnerable to code injection (frequency). Finally, some tools like SQLMap allow to automatically detect and use these vulnerabilities (exploitation). For this reason, the vulnerability is listed in the top 10 published by the Open Web Application Security Project (OWASP) [1]. In this blog post, we will present one type of code injection, called SQL injection, and we will show how to perform a SQL injection attack with SQLMap.
Filter USB devices with udev (and some PHP code)
USB devices can be a liability : they can be used to exfiltrate data from a computer or server, to plug a hardware keylogger, or to plant a malware. Hence on a managed computer, USB devices should be filtered and whitelisted. In this blog post we show how this can be achieved thanks to udev, and some PHP code.
This website uses cookies. More information about the use of cookies is available in the cookies policy.