Codeception, Software Testing

Super Test your Drupal Site with Codeception!

Automation is one of the buzzword in the current industry. However what if we look at a system where we not only do functional test automation for a Drupal site, but also enable developers to write unit tests and the Product Owners/ QA’s write acceptance tests all under a single hood.

Why to Automate!

Developers are often worried how to lower down the leaking of bugs into the production servers. Testers on the other hand cannot continuously test old functionality manually, this is where Automated tests come into play.

Why we used Codeception!

  • Love for Drupal: With love for drupal comes care. To improve the quality we needed a tool that could use both human readable (Gherkin) and drupal supported language PHP.
  • Community Support: Codeception and Drupal community have created number of modules that provide direct gateway to Drupal core functions. This not only allows the testers to do functional testing; however it also empowers them to do API and Database testing inside the codeception framework.
  • One Tool Super Power: One of main advantage of codeception is that it enables teams to do unit, functional and acceptance testing.
  • Developers can leverage it for Unit tests while as QA And Business facing people can write Functional and Acceptance tests easily.
  • Scalable: We can also write custom suites that can be scaled further for more automated tests. With a lot of test automation moving towards BDD, Codeception also has support for Gherkin along with providing the capability to write php code directly. Thereby making it usable for both QA and Business folks.

Codeception tests are written in two formats, namely cept and cest.

Their format is the only difference. Cept is a scenario-based format and Cest is a class based format.

Sample Cept:

$I = new AcceptanceTester($scenario);
$I->wantTo(‘Navigate to the site’);
$I->see(‘Welcome to The Site’);


Sample Cest:

class TestCest
public function _before()

public function _after()
// tests
public function testMe()

//test code here


How we used codeception with Drupal to write tests:

Connecting Codeception with Drupal:

So for getting started with codeception we just need to run following commands:

$ composer require “codeception/codeception”
$ php vendor/bin/codecept bootstrap

These commands need to be run at your Drupal projects root folder. As soon as you run above commands, a tests folder will get created. Inside that folder you will see separate subfolders for unit, acceptance and functional tests.

Getting started with writing simple Acceptance Tests:

With codeception writing Acceptance tests is just one command away

$ php vendor/bin/codecept generate:cept acceptance LoginTest

vendor/bin/codecept → This is the location where the codecept file is present
generate:cept → This is used to tell codeception that the file to be created is of type cept
acceptance -> This is used to decide which folder the test file needs to be created in

LoginTest → This is the name of the test file that we create. With this command an acceptance test file LoginTestCept.php will be created in tests/acceptance/ folder

The same command as above can be modified slightly to create unit and functional tests.

Basic Acceptance Test:

In our LoginTestCept.php file just add following code:

$I = new AcceptanceTester($scenario);
$I->wantTo(‘Navigate to the site’);
$I->see(‘Welcome to The Site’);

Don’t get scared by $I. It’s an object that mimics the real world tester guy, who performs real world actions like clicking on button, navigating to pages, adding text in the form. Some basic functions are wantTo(), see() or amOnPage()

The Power of PageObject:

At the time of inception of codeception it was difficult for Automation folks to visualise page objects in codception but with release of newer versions this feature was added and had a great acceptance also.
We can think of PageObject as a storage of UI locators.
So for example we have an Drupal Website with /blogs /partners pages.
We can define objects for /blogs page seperately in a class and use them based on the need. This also helps in reusability


class BlogsPage {
const URL = ‘/blogs’;
static $blogList = ‘#list’;
static $newBlogButton = ‘#toolbar’;
static function row($id)
return $blogList .” .blog-$id”;

We can use the above class and its objects easily in our cests or cepts:


$I = new WebGuy($scenario);
$I->wantTo(‘find blog #1 in a list and edit it’);
$I->click(‘Edit’, BlogsPage::row(1));
$I->see(‘Editing Blogs #1’);

We can further use it for improving UI interactions also

Helpers come to rescue:
As our tests get longer and functionality increases it becomes difficult to maintain our automation code. Helpers come to help here.

Example we have a flow to test for writing a blog:

$I = new WebGuy($scenario);
$I->wantTo(‘login and write blog’);
$I->login(uname, pass);

In our helper class we have already defined the steps for login inside login function and similar steps have been added for addBlog function.

How developers can write readable code for better automation testing:
One of the basic problems that automation folks face is regarding locators. Some pages have UI elements with similar locators. If locators are added unique for each element, this eases automation guy’s work.

Codeception comes with support of grouping your tests:
Tests can be grouped into smoke, sanity etc called suites. This is a nice feature of codeception that comes handy while running these suites.


Business folks and developers need Reporting for understanding the impacted areas based on failures.
Codeception provides both HTML and XML reporting.
XML reports can further be extended for custom reports depending on use case.

Drupal Love:
Community has developed lot of modules like drupal mail, drupal variable that enable a tester to access core functionality easily. Also tests involving DB queries can be run easily in codeception.

Continuous Integration :

Codeception has good support on almost all CI frameworks like Jenkins, Travis etc.
This minimises the human intervention for triggering tests manually and also provides reports on the go.

Why Codeception and not Behat:

  • Codeception is built on top of PHPUnit. It has capability for unit, functional and acceptance Tests.
  • Behat is included in Codeception, so I would say you should “switch” to Codeception yesterday. They aren’t exclusive. Anything you are doing using just the Behat framework you can do with Codeception, although the reverse isn’t true.
  • Codeception can handle your Gherkin feature files, and it can also handle files written for PHPUnit [called “Cest” files in Codeception]. Codeception can also handle acceptance and functional tests written in a modified form of Gherkin which are very easy to understand and read [called “Cept” files in Codeception].
  • Finally, Codeception has an extensive Drupal support that is far and away the best PHP testing framework for Drupal [since again, it can also handle the Core PHPUnit tests].
  • As far as Mink is concerned, you don’t really need it with Codeception because it includes drivers for headless [no rendered graphics or JS], as well as full Selenium and PhantomJS Webdrivers. Codeception will understand your Mink code, since Mink is just a Webdriver wrapper.
  • Codeception also makes it easy by separating tests into suites by default. You can use different driver configurations for different suites.