How Not to Drown in Bugs: E2E Testing of PHP Applications

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Why Regular Unit Tests Don't Save You, and What is E2E?

\n\n

Imagine: you've written perfect code. Unit tests are green, coverage is 90%, the architecture is a gem. You roll out a release... and users complain that the "Pay" button doesn't work, even though all records in the database are correct. Sound familiar?

\n\n

The problem is that unit tests check isolated pieces of code. They don't see how your PHP method interacts with the JavaScript validator on the frontend, how the session is passed via cookies, or what happens when Redis suddenly goes down. This is where E2E (End-to-End) testing comes into play.

\n\n

E2E tests simulate real user behavior: clicking buttons, filling out forms, checking redirects and API responses. In the PHP world, this is especially relevant because a typical application is a complex tangle of Laravel/Symfony, databases, queues, and external services. Without E2E, you risk missing bugs that will ruin the user experience.

\n\n

Tools for E2E Testing of PHP Projects

\n\n

In the PHP ecosystem, there are two main players. I won't keep you in suspense — here they are:

\n\n
    \n
  • Codeception — the most popular framework that combines unit, functional, and E2E tests. It supports Selenium WebDriver, PHPBrowser, and REST API out of the box.
  • \n
  • PHPUnit + Selenium WebDriver — a classic combination where PHPUnit handles execution and Selenium handles browser emulation. Requires more manual configuration but gives you full control.
  • \n
\n\n

Personally, I recommend Codeception for getting started: it works well with popular CMS (WordPress, Drupal) and frameworks (Laravel, Yii2), and configuration takes 10 minutes.

\n\n

Installing Codeception for E2E

\n\n

Create a composer.json file in the project root (if it doesn't exist) and run:

\n\n
composer require --dev codeception/codeception codeception/module-webdriver codeception/module-phpbrowser
\n\n

Then initialize the framework:

\n\n
vendor/bin/codecept init
\n\n

You will be asked what type of tests to create. Choose Acceptance (E2E). After that, the tests/acceptance folder and the codeception.yml config file will appear.

\n\n

Writing Your First E2E Test: User Registration

\n\n

The most common scenario is registration. Let's check that the form works correctly and that the user sees a greeting after submission.

\n\n

Configuration for Working with a Browser

\n\n

Open tests/acceptance.suite.yml and configure the WebDriver module (for Chrome):

\n\n
actor: AcceptanceTester\nmodules:\n    enabled:\n        - WebDriver:\n            url: 'http://localhost:8000'  # URL of your local server\n            browser: chrome\n            window_size: 1920x1080\n            capabilities:\n                chromeOptions:\n                    args: ["--headless", "--no-sandbox"]  # headless for CI\n        - Db:\n            dsn: 'mysql:host=localhost;dbname=testdb'\n            user: 'root'\n            password: ''\n            populate: true\n            cleanup: true\n
\n\n

Important: don't forget to start the Selenium Server (or ChromeDriver) in a separate terminal:

\n\n
java -jar selenium-server-standalone.jar
\n\n

Test Code

\n\n

Create a file tests/acceptance/RegistrationCest.php:

\n\n
<?php\nuse Codeception\\Util\\Locator;\n\nclass RegistrationCest\n{\n    public function _before(AcceptanceTester $I)\n    {\n        $I->amOnPage('/register');\n    }\n\n    public function testSuccessfulRegistration(AcceptanceTester $I)\n    {\n        // 1. Fill out the form\n        $I->fillField('input[name="name"]', 'Ivan Petrov');\n        $I->fillField('input[name="email"]', 'ivan@example.com');\n        $I->fillField('input[name="password"]', 'StrongPass123!');\n                

Blogs

Book Recommendations