Writing acceptance tests

Introduction

Acceptance testing in TYPO3 world is about piloting a browser to click through a frontend generated by TYPO3 or clicking through scenarios in the backend.

The set up provided by typo3/testing-framework and supported by runTests.sh and docker-compose.yml as outlined in the styleguide example is based on codeception and selenium, usually using chrome as browser.

Similar to functional testing, acceptance tests set up an isolated TYPO3 instance that contains everything needed for the scenario. In contrast to functional tests, though, one test suite that contains multiple tests relies on a single instance: With functionals, each test case gets it’s own instance, with acceptance tests, there is typically one test suite with only one instance and all tests are executed in this instance. As a result, tests may have dependencies between each other. If for instance one acceptance tests created a scheduler tasks, and a second one verifies this task can be deleted again, the second task depends on the first one to be successful. Other than that, the basic instance setup is similar to functional tests: Extensions can be loaded, the instance can be populated with fixture files and database rows and so on.

Again, typo3/testing-framework helps with managing the instance and contains some helper classes to solve various needs in a typical TYPO3 backend, it for instance helps with selecting a specific page in the page tree.

Set up

Extension developers who want to add acceptance tests for their extensions should have a look at the styleguide example for the basic setup. It contains a codeception.yml file, a suite, a tester and a bootstrap extension that setup up the system. The bootstrap extension should be fine tuned by extensions to specify - similar to functional tests - which specific extensions are loaded and which database fixtures should be applied.

Preparation of the browser instance and calling codeception to execute the tests is again performed by runTests.sh in docker containers.

Backend login

The suite file (for instance Backend.suite.yml) should contain a line to load and configure the backend login module:

modules:
  enabled:
    - \TYPO3\TestingFramework\Core\Acceptance\Helper\Login:
      sessions:
        # This sessions must exist in the database fixture to get a logged in state.
        editor: ff83dfd81e20b34c27d3e97771a4525a
        admin: 886526ce72b86870739cc41991144ec1

This allows an editor and an admin user to easily log in to the TYPO3 backend without further fuzz. An acceptance test can use it like this:

<?php
declare(strict_types = 1);
namespace TYPO3\CMS\Styleguide\Tests\Acceptance\Backend;

use TYPO3\CMS\Styleguide\Tests\Acceptance\Support\BackendTester;
use TYPO3\TestingFramework\Core\Acceptance\Helper\Topbar;

class ModuleCest
{
    /**
     * @param BackendTester $I
     */
    public function _before(BackendTester $I)
    {
        $I->useExistingSession('admin');
    }

The call $I->useExistingSession('admin') logs in an admin user into the TYPO3 backend and lets it call the default view (usually the about module).

Frames

Dealing with the backend frames can be a bit tricky in acceptance tests. The typo3/testing-framework contains a trait to help here: The backend tester should use this trait, which will add two methods. The implementation of these methods takes care the according frames are fully loaded before proceeding with further tests:

// Switch to "content frame", eg the "list module" content
$I->switchToContentFrame();

// Switch to "main frame", the frame with the main modules and top bar
$I->switchToMainFrame();

PageTree

An abstract class of typo3/testing-framework can be extended and used to open and select specific pages in the page tree. A typical class looks like this:

<?php
declare(strict_types = 1);
namespace TYPO3\CMS\Core\Tests\Acceptance\Support\Helper;

use TYPO3\CMS\Core\Tests\Acceptance\Support\BackendTester;
use TYPO3\TestingFramework\Core\Acceptance\Helper\AbstractPageTree;

/**
 * @see AbstractPageTree
 */
class PageTree extends AbstractPageTree
{
    /**
     * Inject our core AcceptanceTester actor into PageTree
     *
     * @param BackendTester $I
     */
    public function __construct(BackendTester $I)
    {
        $this->tester = $I;
    }
}

This example is taken from the core extension, other extensions should use their own instance in an own extension based namespace. If this is done, the PageTree support class can be injected into a test:

<?php
declare(strict_types = 1);
namespace TYPO3\CMS\Core\Tests\Acceptance\Backend\FormEngine;

use Codeception\Example;
use TYPO3\CMS\Core\Tests\Acceptance\Support\BackendTester;
use TYPO3\CMS\Core\Tests\Acceptance\Support\Helper\PageTree;

class ElementsBasicInputDateCest extends AbstractElementsBasicCest
{
    public function _before(BackendTester $I, PageTree $pageTree)
    {
        $I->useExistingSession('admin');

        $I->click('List');
        $pageTree->openPath(['styleguide TCA demo', 'elements basic']);

        ...
    }
}

The example above (adapt to your namespaces!) instructs the PageTree helper to find a page called “styleguide TCA demo” at root level, to extend that part of the tree if not yet done, and then select the second level page called “elements basic”.

ModalDialog

Similar to the PageTree, an abstract class called AbstractModalDialog is provided by typo3/testing-framework to help dealing with modal “popups” The class can be extended and used in own extensions in a similar way as outlined above for the PageTree helper.