symfony4 -- Функциональные тесты (Functional Tests). Что это. Пример.

Функциональные тесты нужны, функциональные тесты важны:

  • для проверки корректной связи между уровнями вашего приложения (от роутинга до представления) - чтобы проверять, не сломалили ли вы чего ненароком, пока писали код
  • для моделирования ожидаемого поведения внешнего сервиса, если вы используете их в Вашем приложении - чтобы проверять, не произошли ли какие-либо изменения в работе внешнего сервиса и не сломали ли ваш код

Первым делом

установите необходимые пакеты, если они не установлены:

composer require --dev symfony/phpunit-bridge

composer require --dev symfony/browser-kit

Создаём Контроллер

Именовать контроллер принято так: Имя оригинального контроллера + Слово Test.
Наследуем наш класс от WebTestCase - класса, содержащего все инструменты для работы теста:

// tests/Controller/MyControllerTest.php:
namespace App\Tests\Controller;

use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

class MyControllerTest extends WebTestCase
{
    // это эмулятор браузера в вашем тесте
    // вынесем его создание в конструктор класса, т.к. использовать его нам придётся в каждом методе
    protected $client;

    public function __construct() {
        $this->client = static::createClient();
    }

    /**
     * Проверяет корректность ответа при определённом запросе
     */
    public function testMyAction(): void
    {
        // такой запрос отправляем
        $this->client->request(
            'GET',
            '/my-route',
            [
                'parameter' => 'value',
            ]
        );

        // такой ответ ожидаем 
        $response = $this->client->getResponse();
        
        // дальше начинаем проверять:
        // Проверка на эквивалентность
        $this->assertEquals(200, $response->getStatusCode());

        // так можно достать тело ответа
        $content = $response->getContent();

        // Проверка на Json
        $this->assertJson($content);
        $result = json_decode($content, true);

        // Проверка на true
        $this->assertTrue(is_array($result));

        // Проверка массива на наличие в нём определённого ключа
        $this->assertArrayHasKey('count', $result);
        $this->assertArrayHasKey('items', $result);

        // Допустим, мы ожидаем, что на наш запрос вернётся массив со значением 'count' = 0
        $this->assertEquals($result['count'], 0);
        
        // Проверка на пустоту
        $this->assertEmpty($result['items']);

        // И так далее - проверяем все ключи ответа
    }
}

И такие методы необходимо создать для каждой ветки, которую имеет ваше приложение.
Например, все варианты ответов с кодом 200 (для каждого запроса могут возвращаться разные ключи массивов, пустые данные, конкретные данные, всё заведомо известное поведение), а также можно смоделировать запрос с ошибкой 400 (BadResuest).

Чем больше возможных вариантов "покроют" ваши тесты, тем лучше. Приемлимым считается уровень покрытия - 80%.

Ссылки, формы, кнопки и др. html-элементы

Если ответ приходит в виде HTML или XML, используйте для тестирования объект Гусеничный трактор, или Медленно едущий извозчик (Crawler :)))).
Подробнее смотрите в документации.

Запуск тестирования

Запускаются тесты консольной командой:

./vendor/bin/simple-phpunit

Источники