Migrate Codeception tests to DDEV selenium add-on

If you read my other blog posts or followed my older posts on Twitter or the newer once in the Fediverse, you may already know, that I like my projects based on DDEV, and Codeception is my preferred acceptance testing framework.

Long time, I used a setup where I needed to install a selenium server and chromedriver on my local machine. This was ok as long, as I was the only one who ran the tests. But a soon as I wanted to motivate my coworkers to start writing or executing the tests, this always was additional work.
And especially when having visual regression tests, the different screen resolutions and pixel densities made it nearly impossible, to have the tests run on different computers.

But as always, there is hope. Several time ago, a DDEV Selenium Standalone Chrome add-on was released.
Here I show, how I migrated my codeception tests from local selenium server on the host system to DDEV selenium add-on. If you were looking for a beginner tutorial to start with codeception tests, I'm sorry.

Install the add-on #

ddev get ddev/ddev-selenium-standalone-chrome
ddev restart

I suggest to commit the generated files to Git. The benefit is, that all your coworkers immediately have the plugin available after they start the container. The downside is, this is a bit of wasted performance, if you don't need it.

Configure Codeception's WebDriver #

In the most cases, the configuration can be found in acceptance.suite.yml. (There may be cases when it is in the root codeception.yml, but it will look very similar.)

My old way with local selenium server needed the setting host: host.docker.internal. The new value is host: selenium-chrome.

The next step is to tell the browser to accept DDEV's self generated SSL certificates, which can be done with the additional argument --ignore-certificate-errors and to disable the shared memory usage by --disable-dev-shm-usage. Maybe you will find dozens of other solutions for the share memory problem, but this is mine, and it works for me.

Here a full example of a valid acceptance.suite.yml file:

actor: AcceptanceTester
modules:
  enabled:
    - WebDriver:
        url: https://myproject.ddev.site
        host: selenium-chrome
        browser: chrome
        capabilities:
          goog:chromeOptions:
            args:
              - '--ignore-certificate-errors'
              - '--disable-dev-shm-usage'

Use DDEV command to run tests #

To make life easier, I add a file named .ddev/commands/web/acceptancetests with the following content to all our projects.

#!/bin/bash

## Description: Run codeception acceptance tests
## Usage: acceptancetests [test] [options]
## Example: ddev acceptancetests or ddev acceptancetests RegistrationCest --debug

echo "🖥️  Visit ${DDEV_PRIMARY_URL}:7900 and enter the password \"secret\" to watch the tests running."
vendor/bin/codecept run acceptance "$@" --html

This simplifies the command to run the tests and also provides a hint how to use noVNC to watch the tests, wich is shipped with the DDEV Selenium Standalone Chrome add-on by default.

To run all tests I simply need to type:

ddev acceptance

Of if I want, I can also pass other options:

ddev acceptance MyCest
ddev acceptance MyCest::testSomething
ddev acceptance MyCest::testSomething --debug

That's all! You're done! Except you are using ...

Multiple host names #

I won't cover how to configure multiple domains in a codeception configuration. I do it with separate environments.

Let's assume, we have https://myproject.ddev.site configured as first environment with name "domain1" and https://alsomyproject.ddev.site as environment with name "domain2"

Configure additional routes #

To let the selenium-chrome container know how to resolve the additional domain, I create a file .ddev/docker-compose.selenium-chrome.override.yaml with the following content:

#
# This file is required to register additional domains than only the default domain for selenium chrome.
# This configuration is not part of docker-compose.selenium-chrome.yaml to not being overwritten when regenerated.
#
services:
  selenium-chrome:
    external_links:
      - ddev-router:alsomyproject.${DDEV_TLD}

A) Extend DDEV command #

If you want to run your tests against all environments, wenn running ddev acceptancetests, you may change this line in the DDEV command:

vendor/bin/codecept run acceptance "$@" --html

into this:

vendor/bin/codecept run acceptance "$@" --env domain1 --env domain2 --html

B) Not extend DDEV command #

Or if you want to explicitly select the environment, you can keep it untouched and add the --env options to the command:

ddev acceptancetests --env domain1 --env domain2
ddev acceptancetests --env domain2
ddev acceptancetests --env domain1

Update #

In June 2024, I posted a new article how to use a newer Chromium version