Add selenium acceptance tests to codeception with yii2 on docker-compose setup to run seamlessly with test settings

Here we will discuss steps needed to add selenium acceptance tests with codeception to existing yii2 project with docker-compose setup that uses nginx as the http server with FCGI. The problem with acceptance tests is that the testing browser will access the app through the main files, not through the testing files, as it is done automatically by codeception with yii2 plugin for other types of tests. This technique maybe useful for those running other servers.

Considering you already have your yii2 project with codeception enabled, running in docker-compose and now you want to add selenium acceptance tests.

Recommendation: I’ve had problems with codeception 3 with Acceptance Helper plugin, so I upgraded to codeception 4, getting rid of codeception 3 and yii2-codeception altogether. Codeception 4 provides migrating scripts that do the tedious work of adding needed plugins and extensions. Mine project upgrade was a bliss. Have to mention that the upgrading procedure adds new needed codeception modules to composer.json and then runs “composer update”. And you should repeat it for each codeception config directories, so it may take long for yii2 advanced apps, depending on your composer update time and numbers of apps in the advanced project. So, to upgrade: uninstall codeception and yii2-codeception using composer, install codeception 4 using composer and run the upgrade script. That should do the trick. Run your tests to check if the upgrade was ok.

Regardless whether you upgraded to codeception 4 or not, the steps should work fine.

Add selenium-standalone, for example the chrome one, to your docker-compose.yml, like that:

1
2
3
4
5
  http:
    ...
  selenium-chrome:
    image: selenium/standalone-chrome
    shm_size: "2G"

If these are the names of the containers, your new acceptance.suite.yml in the tests folder should look like this:

1
2
3
4
5
6
7
8
9
10
11
# acceptance.suite.yml
actor: AcceptanceTester
modules:
  enabled:
#    - \Helper\Acceptance # this is from the docs, but no luck with this setting. you may try it, though.
    - Asserts:
    - WebDriver:
        url: 'http://http/' # it's the name of the nginx container from your docker-compose
        host: 'selenium-chrome'  # it's the name of the selenium-chrome container from your docker-compose
        port: 4444 # default port
        browser: chrome # 'chrome' or 'firefox'

also, create the corresponding acceptance folder nearby the acceptance.suite.yml.

Now you may run the codeception build to see if things are set up ok.

Now we need to make the app accessible through the index-test.php parts for the selenium. We will alter nginx fcgi for PHP that is requested through http domain name to pick up index-test.php instead of index.php. It means that the developers on their local machines should develop through another hostname.

So, in your nginx.conf repeat your default server config, but add

1
server_name http;

and in that block replace all “index.php” with “index-test.php”. Reload nginx config or restart containers.

Now go to your index-test.php, you’ll find there block of code that prevents non-local http requests. Add a bypass there:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$headers = getallheaders();
//print_r($headers);
// for acceptance selenium tests workaround
if(
    is_array($headers)
    && array_key_exists('Host', $headers)
    && $headers['Host'] === 'http'){
 // allow, do nothing
} else {


    // NOTE: Make sure this file is not accessible when deployed to production
    if (!in_array(@$_SERVER['REMOTE_ADDR'], ['127.0.0.1', '::1'])) {
        die('You are not allowed to access this file.');
    }

}

There you are, you may now run selenium tests on your test database with tests setup.

Be sure that you do not deploy index-test.php to your production servers.