Какие тесты ты пишешь: функциональные или юнит тесты?
Что проверяют
Интервьюер хочет услышать не «пишу и те и другие», а как вы делите проверки между уровнями и какими инструментами PHP-экосистемы пользуетесь. Следом обычно спрашивают, как вы работаете с базой в тестах и что мокаете.
Как отвечать
Разведите понятия: юнит-тест проверяет класс в изоляции, без базы, фреймворка и сети, функциональный проверяет фичу через внешний интерфейс, обычно HTTP-запрос к приложению с настоящей базой. Дальше конкретика по стеку:
- PHPUnit: основа всего. В свежих версиях метаданные задаются атрибутами
#[Test],#[DataProvider],#[CoversClass], аннотации в докблоках больше не поддерживаются. Моки черезcreateMock()или Mockery; - Pest: надстройка над PHPUnit с более коротким синтаксисом, популярна в Laravel-проектах;
- Laravel: каталоги
tests/Unitиtests/Feature, запросы через$this->postJson()с проверкойassertStatus()иassertJson(), трейтRefreshDatabase, фабрики моделей,Http::fake()иQueue::fake()для внешних вызовов; - Symfony:
KernelTestCaseдля сервисов из контейнера,WebTestCaseдля HTTP-сценариев; - Behat или Codeception: если в проекте BDD или приёмочные сценарии;
- Infection: мутационное тестирование, показывает, ловят ли тесты изменения в коде, а не только проходят ли по строкам.
Принцип распределения: ветвистую доменную логику и расчёты выгодно покрывать юнит-тестами, а маршруты, валидацию запросов, права доступа и работу с Eloquent или Doctrine видно только в функциональных.
Приводите свои цифры: число тестов, время прогона в CI, покрытие, конкретный баг, который поймал тест. Если функциональные тесты писали не вы, скажите об этом прямо.
Где спотыкаются
Считают юнит-тестами всё, что лежит в tests/Unit, хотя тесты там наследуют Tests\TestCase, поднимают приложение и ходят в базу. Уровень теста определяют зависимости, а не каталог.
Мокают модели Eloquent и фасады там, где проще прогнать функциональный тест с RefreshDatabase на тестовой базе.
Не изолируют данные между тестами. Порядок запуска начинает влиять на результат, и параллельный прогон через ParaTest превращается в лотерею.