In the first two tests, we reviewed and tested the code. In this section, we’ll test what data is actually being transmitted and what users actually see.
What Cucumbers Have to Do with Tests
For all of the following tests, we’ll use the same test code stack—we’ll use Codeception as the test runner and, within it, the concept of Behavior-Driven Testing, which uses the Gherkin language.
Gherkin code looks like this:
As you can see, this syntax focuses on user interaction—CSS selectors are rarely used; instead, a task is typically described in the same way a user would use the application.
Thanks to the relatively simple steps and the focus on the actual content of the website, it’s possible to map out very complex workflows—and, as with the other tests, no logic is hidden. You’ll also recognize the AAA pattern again, where “Act” and “Assert” are performed multiple times in any order.
Acceptance Testing for the Functions
But what is actually being tested here? The sample code demonstrates an acceptance test. This test controls a browser—either a standard Chrome browser with all features or a headless Chrome instance running inside a Docker container in the development and CI environment—and clicks its way through the finished application.
We define acceptance tests such that, before the test run, a defined database state stored in Git is imported—which can be optionally supplemented for each test—and then the test is executed. At the end of each test, the database is reset to the defined state. This allows any process to be tested as often as needed—for example, user creation. If the database state were not always the same, the test could only be run once, since a user with a given username can only be created once; and if a second test were needed to delete the user, these tests would have to be run sequentially to avoid causing inconsistencies.
These tests always cover the entire application stack—web server configuration, Backend, and front-end code, CSS (for example, `display: none` affects test calls like “I should see”), the database and content, the contents of the file system—you name it, you test it. Of course, it’s important to note that tests which render the website or app and involve multiple clicks, form fills, and submissions can take a correspondingly long time to run, which is why these tests are typically used not as the primary method but as a supplement to other, faster tests.
Faster API Testing
Our biggest project right now is a React application with a TYPO3Backend. The tests were taking too long (even with parallelization and similar techniques), especially when we wanted to verify the correct data visibility for different permissions and for users who weren't logged in. For this purpose, we’re therefore using API tests, which are also written in Gherkin with Codeception but use Guzzle internally.
These tests have slightly different steps (example: “Given that the API is logged in as 'user'”), which instructs Codeception to have Guzzle execute the commands, allowing us to directly test the API URLs, the requests and responses via JSON calls, and the database contents. The advantage is that while simple acceptance tests—such as a login with a check of the homepage content—take 4 seconds, the API-only stage requires only a few milliseconds for a similar test.
Our workflow often involves the API checking the various scenarios and data (no login, different permissions, valid data, invalid data, data from the past/today’s, or future data, etc.), and the full-stack tests then verify that the application behaves correctly in both successful and error scenarios. In addition, we also test front-end-specific functions in the full-stack, such as whether form fields behave differently depending on what a user enters.
We want to catch errors before they affect our customers
We also use Codeception and Gherking for a third testing suite. The full-stack and API tests are always run on every commit and against the main Git branch whenever changes occur, but they only cover the state of the development environment. With the third suite, we test features directly on the customer’s live system.
Here, too, we use the browser and user-like steps, but we make sure not to modify any data within the tests and not to check for modifiable data—for example, when calling an activity (as in the sample code above), we do not check for an exact date or an exact first and last name; instead, we test to ensure that any date and any name are displayed—this information is sufficient for us to know that our production system is rendering the content correctly.
The goal of these tests is to ensure that, after deployments or nightly imports and similar processes, we know the production system is still functioning; and if it isn’t, we want to be notified before it affects actual website users. In an older project, there was actually a case where tests around 8:00 a.m. alerted us to a bug—we were able to fix it within a few minutes, and when users began using the application between 8:30 and 9:00 a.m., they were able to do so without any issues.
Tools Used
The Codeception framework provides methods that you can program yourself to translate Gherkin syntax into Codeception calls. We’ve divided standard steps that are used repeatedly into various Composer packages and published them on GitHub and Packagist. These repositories are located in the Account/Vendor section of punkt.de, including a small demo project where you can see how to use them.
Graduation
This was the final part of our testing series. Applications can now be tested—from code quality to proper functionality on the live system.
Agile Testing and Process Expertise for Your Team:
Whether you’re an agency, an industrial company, or an independent development team: If you want to establish or further develop agile testing processes, we’ll support you with our expertise—whether through hands-on workshops or by working directly on your projects. We’ll guide you through every step—from introducing agile testing methods and optimizing existing processes to developing and implementing customized testing strategies.
Feel free to contact us so we can work together to take your quality assurance and development processes to the next level!