Testing with Selenium and PHPUnit

Aug 8, 2021 by Thibault Debatty | 2160 views

PHP DevOps


In this blog post we continue our series about testing a web application with Selenium. This time we will show how to integrate Selenium with PHPUnit tests and assertions.

PHPUnit tests

To help you write PHPUnit tests that rely on Selenium, you can use the phpunit-selenium extension. However, at the time of writing, there is an incompatibility between phpunit-selenium and phpunit >= 9.4. So you must force phpunit version 9.3.x in order to use phpunit-selenium:

composer require --dev phpunit/phpunit:9.3.*
composer require --dev phpunit/phpunit-selenium

To run my Selenium tests appart from other unit tests, I usually like to create a dedicated phpunit configuration file, for example phpunit-selenium.xml, with following content:

<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd" bootstrap="vendor/autoload.php" colors="true">
    <testsuite name="Selenium">
      <directory suffix="Test.php">./tests/Selenium</directory>

As you can see from the configuration file, the test files must be located in directory tests/Selenium and must end with Test.php.

So you should first create the appropriate directory:

mkdir -p tests/Selenium

Then you can create your first test file, tests/Selenium/ExampleTest.php:


namespace TestsSelenium;

use PHPUnitExtensionsSelenium2TestCase;

class ExampleTest extends Selenium2TestCase
    private $baseUrl = 'http://staging.myapp.com';

    protected function setUp() : void

        $selenium_host = getenv("SELENIUM_HOST");
        if ($selenium_host === false) {
            $selenium_host = "localhost";
        // https://github.com/giorgiosironi/phpunit-selenium/issues/439#issuecomment-561740660
        $this->setDesiredCapabilities(['chromeOptions' => ['w3c' => false]]);

     * @test
    public function testRegisterLink() : void
            "Cyber-Wise helps you to defeat cybercriminals",
            "Register for Cyber-Wise",

As you can see from the example, your tests must extend the class Selenium2TestCase. This class provides several methods to configure your Selenium session, that you will use in your setUp method:

  • setHost
  • setBrowser
  • setBrowserUrl

Selenium2TestCase also provides several methods to select an element on the page:

  • byId
  • byName
  • byXPath
  • byClassName
  • byLinkText
  • ...

Then you can either inspect or interact with the element with following methods:

  • text
  • value
  • click
  • name
  • submit
  • ...

Running tests locally

As you might recall from our previous blog post about Selenium, Selenium is actually a server that can control and drive a real web browser. The easiest way to run Selenium is using docker. In the command below, we will run Selenium together with an instance of the Chrome web browser:

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

Once Selenium is up and running, you can run your PHPUnit tests:

./vendor/bin/phpunit -c phpunit-selenium.xml -v


Finally, you can integrate this test in your GitLab pipeline by adding the following job to your .gitlab-ci.yml. You should modify the stage value such that your test takes place after the new code has been deployed to your staging environment:

  stage: staging-test
  image: cylab/php74
    - selenium/standalone-chrome:3.141.59-20210311
    - composer install
    - SELENIUM_HOST="selenium-standalone-chrome" vendor/bin/phpunit -c phpunit-selenium.xml -v

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.