Codeception Tests with DDEV and Selenium
Tomas Norre Mikkelsen
Posted on March 28, 2020
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
Posted on March 28, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.