Back to Blog

Automated Testing with Symfony and Codeception: A Beginner’s Guide

Automated Testing with Symfony and Codeception: A Beginner’s Guide

Automated testing is a critical part of modern software development, allowing developers to catch bugs early and ensure that their code works as expected. Symfony is a popular PHP web framework that provides many built-in tools for testing, while Codeception is a powerful testing framework that can be used with Symfony to write tests more easily and efficiently.

In this blog post, we’ll provide a step-by-step guide on how to set up automated testing with Symfony and Codeception, complete with code examples. We’ll show you how to create a basic test suite, write and run functional and unit tests, use fixtures to create test data, write acceptance tests using Symfony’s Panther browser automation tool, and use test doubles to isolate code under test.

Whether you’re new to automated testing or just looking to improve your testing skills, this blog post will provide a comprehensive guide on how to use Symfony and Codeception to create robust and reliable tests for your PHP web applications. So let’s get started!

Setting up a Symfony project for automated testing

Before we can start writing automated tests for our Symfony project, we need to make sure that our project is set up to support testing. Here’s how to get started:

Step 1: Create a new Symfony project

To create a new Symfony project, you can use the Symfony CLI. Open up a terminal and enter the following command:

1 symfony new my_project_name

Replace my_project_name with the name of your project. This command will create a new Symfony project in a directory with the same name as your project.

Step 2: Install Codeception and its Symfony module

Codeception is a testing framework that can be used to write functional and unit tests for PHP applications. To install Codeception and its Symfony module, we’ll use Composer. Open up a terminal and navigate to the root directory of your Symfony project, then enter the following commands:

1 2 composer require --dev codeception/codeception composer require --dev codeception/module-symfony

These commands will install Codeception and the Symfony module into your project’s dev dependencies.

Step 3: Create a basic test suite

Now that we have Codeception and its Symfony module installed, we can create a basic test suite for our project. Enter the following command in your terminal:

1 vendor/bin/codecept bootstrap

This command will create a tests directory in your project’s root directory, along with some basic configuration files for Codeception.

Congratulations, you’ve set up a Symfony project for automated testing with Codeception! In the next section, we’ll take a look at how to write and run tests using Codeception and Symfony’s BrowserKit.

Writing and running functional tests

Functional tests are used to test the behavior of your application’s controllers and views. They simulate user interactions with your application, such as clicking links and submitting forms, and verify that the application responds correctly.

Here’s how to write and run functional tests with Symfony and Codeception:

Step 1: Generate a functional test

To generate a new functional test, enter the following command in your terminal:

1 vendor/bin/codecept generate:functional test_name

Replace test_name with the name of your test. This command will generate a new test file in the tests/functional directory, along with some basic code for testing a Symfony controller.

Step 2: Write a functional test

Open up the test file that was generated in the previous step and modify it to test your own Symfony controller. Here’s an example test that verifies that the homepage of your application loads successfully:

1 2 3 4 5 public function testHomepage() { $this->client->request('GET', '/'); $this->assertSame(200, $this->client->getResponse()->getStatusCode()); }

In this test, we use Symfony’s BrowserKit to simulate a GET request to the homepage of our application, and we assert that the response code is 200 (which indicates a successful response).

Step 3: Run the functional test

To run the functional test, enter the following command in your terminal:

1 vendor/bin/codecept run functional

This command will run all of the functional tests in your test suite. If the test passes, you should see output similar to the following:

1 2 3 Functional Tests (1) ----------------------------- ✔ Homepage (0.03s) -------------------------------------------------

Congratulations, you’ve written and run your first functional test with Symfony and Codeception! In the next section, we’ll take a look at how to write and run unit tests.

Writing a unit test for a service in Symfony

In Symfony, a service is a PHP object that performs a specific task or provides a specific functionality. Services are defined in the services.yaml file in the config directory of your Symfony project. They can be used throughout your application, and can also be tested independently of the rest of your application using unit tests.

Here’s an example of how to write a unit test for a service in Symfony:

Step 1: Create a new service

To create a new service, open up the services.yaml file in the config directory of your Symfony project and define a new service with a unique name. For example:

1 2 3 4 # config/services.yaml services: my_service: class: App\Service\MyService

This creates a new service called my_service that is an instance of the App\Service\MyService class.

Step 2: Write a unit test for the service

Create a new test file in the tests/Unit/Service directory of your Symfony project, for example MyServiceTest.php. In this file, create a new test case that extends Symfony\Bundle\FrameworkBundle\Test\KernelTestCase. This class provides a convenient way to bootstrap the Symfony kernel in your test case, which makes it easy to access your services.

Here’s an example test that verifies that the my_service service returns the correct output:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 // tests/Unit/Service/MyServiceTest.php namespace App\Tests\Unit\Service; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; use App\Service\MyService; class MyServiceTest extends KernelTestCase { public function _before() { self::bootKernel(); } public function testMyService() { $myService = self::$container->get(MyService::class); $this->assertEquals( 'expected output', $myService->doSomething() ); } }

In this test, we first boot the Symfony kernel, which initializes the container and makes our services available. We then retrieve the my_service service from the container using self::$container->get(MyService::class), and call the doSomething() method on the service. Finally, we assert that the output of the method matches our expected output.

Step 3: Run the unit test

To run the unit test, enter the following command in your terminal:

1 vendor/bin/phpunit tests/Unit/Service/MyServiceTest.php

This command will run all of the functional tests in your test suite. If the test passes, you should see output similar to the following:

1 2 3 4 5 6 7 Codeception PHP Testing Framework v4.1.24 Powered by PHPUnit 9.5.10 by Sebastian Bergmann and contributors. Unit Tests (1) ---------------------------------------------------------------------------------------------------------------------------------- ✔ MyServiceCest: MyService returns expected output (0.00s) -------------------------------------------------------------------------------------------------------------------------------------------------- Time: 00:00.006, Memory: 6.00 MB OK (1 test, 1 assertion)

This output indicates that the test passed successfully, with 1 test and 1 assertion. If the test had failed, Codeception would have output an error message indicating which assertion failed and what the expected and actual values were.

Advanced topics in automated testing

Fixtures

Fixtures are a common technique used in automated testing to create test data for your application. Fixtures are essentially pre-defined sets of data that can be used to populate your database or other data stores, and they are often used in conjunction with unit tests or functional tests.

By default, Codeception looks for fixture files in a tests/_data directory. You can store your fixture files in this directory to keep them organized and separate from your test files.

To load fixtures from the tests/_data directory, you can use the codecept_data_dir() method, which returns the full path to the data directory. You can then use this path to construct the relative path to your fixture file. Using the codecept_data_dir() method can help you keep your test files organised and make it easier to load fixtures from the tests/_data directory.

Note that we’re using User1 as the fixture key to grab a specific user from the fixture in our test method. This corresponds to the User1 key we defined in our fixture file.

1 2 3 4 5 6 7 8 9 10 # tests/_data/fixtures/users.yml User1: name: John Doe email: john.doe@example.com password: $2y$13$Zjk2OWMwNjI2MTY4OWM4ZO4TA4MDczJh9AjjKtO8ul1C0wHpgpyqi # hashed password User2: name: Jane Doe email: jane.doe@example.com password: $2y$13$Zjk2OWMwNjI2MTY4OWM4ZO4TA4MDczJh9AjjKtO8ul1C0wHpgpyqi # hashed password # ...

In this example, we’re defining two users in our fixture, User1 and User2. We’re providing some basic data for each user, including a name, email, and a hashed password.

You can define as many users as you need in your fixture, and you can include additional data as well. Fixtures can be a powerful way to create realistic test data that accurately reflects the data you’ll be working with in production.

We can then use these fixtures in our tests with the following code:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <?php use Codeception\Test\Unit; class MyServiceTest extends Unit { /** * @var \UnitTester */ protected $tester; public function _before() { // Load fixtures $this->tester->loadFixtures( [ 'users' => codecept_data_dir() . 'fixtures/users.yml', ] ); } public f...

PHP

Symfony

Codeception

Testing

Best Practices