DEV Community


Codecept For Dummies: Part 2: Concepts

kaisershahid profile image kaiser shahid ・3 min read


I went over test basics and how to setup an empty Codecept project (for lack of a better term).

Now I'm going to talk about Codecept's approach to testing. Understanding this will be the key to structuring your actual tests.

Actors (Unit, Functional, Paid Soros Thugs, Whatever)

Tests are executed through the perspective of an actor. An actor has certain expectations:

  • I want to get the contents of
  • I want to verify that there's a search box
  • I want to check if square(2) == 4

In terms of code, it might actually look like this:

  • $html = $I->wantContentFromUrl('')
  • $I->wantToFindElement("input[title='Search']", $html)
  • $I->assertEquals(4, square(2), "unexpected value for square(2)");

Each test suite has a unique actor (e.g. FunctionalTester).


Helpers are Codecept modules -- they're classes that contain methods that an actor can use. Each test suite can define the helpers that get loaded into an actor.

In practice, Codecept will generate a trait with all the methods from all the enabled helpers, and proxy each method to the class actually implementing it. The actor class then uses that trait.


This is the most basic test type. It's basically just a script:

I am on page ''
I see element 'input[title="Search"]'
I set value to 'input[title="Search"]', 'kaiser'
I click 'input[value="Google Search"]'
I get sent to ''

(BTW, you can actually write Cepts like that.)

In this example, we're making the assumption I am on page saves the HTML somewhere where the other steps can refer to it.

If you need finer control, you can convert that to PHP:

$I = new AcceptenceTester($scenario);

$searchEle = 'input[title="Search"]';
$I->setValueTo($searchEle, 'kaiser');
$I->click('input[value="Google Search"]');

For very basic scenarios, write a Cept.


If you need to group your steps together for better reusability, write a Cest:

// in file ExampleCest.php

class ExampleCest {
    public function _fetchStep(FunctionalTester $I, $url) {

    public function checkForSearchBox(FunctionalTester $I) {
        $this->_fetchStep($I, '');

    public function doSearch(FunctionalTester $I) {
        $this->_fetchStep($I, '');
        $I->setValueTo('input[title="Search"]', 'kaiser shahid');
        $I->click('input[value="Google Search"]');

Cests let you collect multiple related scenarios together and allow reuse of common steps. Note that any function starting with _ is not considered a test, so prefix any methods you don't want to automatically execute.

Cest classes must end in Cest, but they can be plain objects by default.

Note that Codecept does dependency injection for Cests! FunctionalTester $I will make Codecept look for FunctionalTester, and if found, initialize it before passing it to the method it's about to execute. We'll get more into this in a future article.

Unit Test

This is what you're probably used to:

// in ExampleTest

class ExampleTest extends \Codeception\Test\Unit {
    public function testScenario1() {
        $this->assertEquals(4, square(2), "unexpected result for square(2)");

Note that the actor is no longer explicit -- its methods are automatically available to the class (probably through __call).

Unit test classes must end in Test and extend \Codeception\Test\Unit. Test scenarios must start with test.


Each test suite has an actor. The actor uses 1 or more helpers to provide test writers assertions and other methods that are useful for that suite. Tests can be very simple scenarios (Cept), scenarios of varying complexity (Cest), or traditional unit tests.

Discussion (0)

Editor guide