DEV Community

Tomas Norre Mikkelsen
Tomas Norre Mikkelsen

Posted on

Codeception Tests with DDEV and Selenium

Running behaviour driven tests like Codeception can bring some advantages to your project, and will help you detect if you break functionality on updates, changes etc.

This blog post will help you setup the basics needed for developing your own tests and running them locally with ddev.

Prerequisits

  • DDEV installed on you local machine
  • Project setup locally with ddev, in this case I will use a plain phpinfo() site to lower complexity.

If you don't have a setup locally already, you can do this by follwoing the ddev get started guide, you can also close my repository on github, then you will not need to do the changes your self to check the prove of concept.

$ git clone https://github.com/tomasnorre/ddev-codeception-poc.git
$ cd ddev-codeception-poc
$ composer install
$ ddev start

If you choose the later one, you can skip the instructions in step 1-3, and go directly to executing the tests, but I would recommend you to do the steps manually.

1. Setup Selenium in DDEV

As you might already know ddev is based on docker, so to setup selenium, we need to add a custom docker-composer.selenium.yml to your ddev setup.

$ cd /path/to/your/local/project/.ddev
$ touch docker-compose.selenium.yaml

Use you default editor to edit the docker-compose.selenium.yaml file. This configuration is take from the Selenium Github Page, with a few adjustments, like the version: '3.6', container_name and removing the firefox and opera part.

version: '3.6'
services:
  selenium-hub:
    image: selenium/hub:3.141.59-20200326
    container_name: ddev-${DDEV_SITENAME}-selenium-hub
    ports:
      - "4444:4444"

  chrome:
    image: selenium/node-chrome:3.141.59-20200326
    container_name: ddev-${DDEV_SITENAME}-chrome
    volumes:
      - /dev/shm:/dev/shm
    depends_on:
      - selenium-hub
    environment:
      - HUB_HOST=selenium-hub
      - HUB_PORT=4444

Now you can restart you ddev project with ddev restart and you will have a selenium container running together with your project.

2. Install Codeception

Steps copied from Codeception QuickStart Guide

$ composer require "codeception/codeception" --dev
$ php vendor/bin/codecept init acceptance

Let's prepare Codeception for acceptance testing
Create your tests and run them in real browser

? Where tests will be stored? (tests)
? Select a browser for testing (chrome)
  [0] chrome
  [1] firefox
 > 0
 Ensure that you have Selenium Server and ChromeDriver installed before running tests
? Start url for tests (http://localhost)
 Created test directories inside at tests
 Adding codeception/module-webdriver for WebDriver to composer.json
1 new packages added to require-dev
? composer.json updated. Do you want to run "composer update"? (y/n) y

After this we know have a codeception.yml in our root folder, next to composer.json and we have a tests folder, also in our root folder, that is created and populated with Codeception setup.

As I didn't adjust the start url as part of the initiation I need to adjust it manually.
Open the codeception.yml and adjust

enabled:
    - WebDriver:
        url: http://localhost/

to

enabled:
    - WebDriver:
        url: http://web/

this will make the Codeception make requests against the docker-container named web, which is your application container, in a default ddev setup.

3. Small Test example

In the tests folder we also have a file LoginCest.php which we are going to adjust, to add new tests.

The naming of the file, isn't important at this stage, but I would suggest to have files and structures match your application and what you're testing, this keeps it easier to find, correct, and add new tests.

Open the tests/LoginCest.php with your editor. Currently it looks like this

<?php
class LoginCest 
{    
    public function _before(AcceptanceTester $I)
    {
        $I->amOnPage('/');
    }

    public function loginSuccessfully(AcceptanceTester $I)
    {
        // write a positive login test 
    }

    public function loginWithInvalidPassword(AcceptanceTester $I)
    {
        // write a negative login test
    }       
}

The _before() is actions that will be executed before every test. The two other tests are empty right now so if you run php vendor/bin/codecept run you will have a green test result.

Let us add some more meaning full tests. First remove the two empty tests and add

public function canSeePHPVersion(AcceptanceTester $I)
{
    $I->canSee('PHP Version 7.4.3');
}

This will check if it finds the string "PHP Version 7.4.3" on the page / as that's the page defined in the _before() function.

Lets run the tests:

$ php vendor/bin/codecept run

Codeception PHP Testing Framework v4.1.4
Powered by PHPUnit 8.5.2 by Sebastian Bergmann and contributors.
Running with seed:


Acceptance Tests (1) -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
✔ LoginCest: Can see php version (1.78s)
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Time: 2.91 seconds, Memory: 12.00 MB

OK (1 test, 1 assertion)

This page used can also be changed by doing

public function canSeePHPVersion(AcceptanceTester $I)
{
    $I->amOnPage('/index.php');
    $I->canSee('PHP Version 7.4.3');
}

If you have failing tests, there will be a link echoed in your terminal

There was 1 failure:

---------
1) LoginCest: Can see php version
 Test  tests/LoginCest.php:canSeePHPVersion
 Step  Can see "PHP Version 7.4.2"
 Fail  Failed asserting that  on page /index.php
--> PHP Version 7.4.3
System Linux ddev-codeception-poc-web 4.19.76-linuxkit #1 SMP Thu Oct 17 19:31:58 UTC 2019 x86_64
Build Date Feb 24 2020 18:39:14
Server API FPM/FastCGI
Virtual Directory Support disabled
Configuration File (php.ini) Path /etc/php/7.4/fpm
Loaded Configuration File /etc/php/7.4/fp
[Content too long to display. See complete response in '/path/to/Projects/ddev-codeception-poc/tests/_output/' directory]
--> contains "PHP Version 7.4.2".

Scenario Steps:

 3. $I->canSee("PHP Version 7.4.2") at tests/LoginCest.php:12
 2. $I->amOnPage("/index.php") at tests/LoginCest.php:11
 1. $I->amOnPage("/") at tests/LoginCest.php:6

Artifacts:

Png: /path/to/Projects/ddev-codeception-poc/tests/_output/LoginCest.canSeePHPVersion.fail.png
Html: /path/to/Projects/ddev-codeception-poc/tests/_output/LoginCest.canSeePHPVersion.fail.html

FAILURES!
Tests: 1, Assertions: 1, Failures: 1.

The png version is a screenshot, so if the text/element you are looking for are below the fold, you will not see it.

The html version is a scrollable version of the page, be aware that this might look quite rubbish, if the Javascript, css etc, isn't loaded correct, which often is the case, so might be difficult to spot the problem.

Conclusion

This is as you see a very small and compact example on how you can run Codeception in DDEV setup.

I'm far from expert on the field, neither ddev nor Codeception, but if you have any questions feel free to reach out to me on https://twitter.com/tomasnorre.

I have also pushed the example setup to my github account, so if you want to discuss something, that could benefit others, you can create an issue at https://github.com/tomasnorre/ddev-codeception-poc/issues

Discussion (0)