Как тестировать запросы и ответы из базы данных через phpunit?

До последнего избегал тестирования, т.к. было отторжение из-за сложности при первом знакомстве с phpunit. Сейчас решил пересилить себя и разобраться в этой теме.

Если с тестированием основной логики относительно понятно (из документации к phpunit), то вот как быть с тестированием запросов к базе данных никак не могу понять.

Погуглив, пришел к нескольким вариантам:
1. Создать тестовую базу данных с фиктивными данными, через setUp() использовать PDO и делать полноценные запросы (насколько понял, данный подход используется в Laravel и Symfony).
2. Использовать Mock, который будет содержать массив с данными симулирующими ответ из базы данных. И вот в этой теме я прям плаваю. А точнее, нифига не могу понять как именно это должно работать.

При поиске более детальной информации, находятся статьи, или для совсем маленьких, или сразу для опытных.

Помогите, пожалуйста, в следующих моментах:
  1. Какой из подходов более предпочтителен в современных реалиях: тестовые базы данных или Mock?
  2. Что можно почитать про тестирование PHP-приложений (статьи, книги)? Желательно с широким охватом (а не только тестирование возврата 2 + 2), пусть поверхностно, но чтобы было понимание общей картины.
  3. Если вдруг нет советов по книгам или материалам, толкните, пожалуйста, в правильном направлении как понять Mock, Stub, Fixtures? Официальную документацию я прочитал от корки до корки три раза, но как будто мне не хватает более расширенных примеров что-ли...
  • Вопрос задан
  • 1164 просмотра
Решения вопроса 1
ipatiev
@ipatiev Куратор тега PHP
Потомок старинного рода Ипатьевых-Колотитьевых
Мне кажется, что найденные варианты работают не так. Используются они оба, а какой именно - зависит от того, что именно вы тестируете - запрос или ответ.

Если говорить про "запросы к БД", то для таких тестов "массив с данными" использовать просто глупо. Это получится какой-то формальный тест: "проверяем, что метод возвращает массив из трех строк - и тут же возвращаем этот самый массив". В чем смысл? Если вы тестируете запрос к БД, то и надо тестировать запрос к БД. По-другому никак.

Здесь я отвлекусь, и порассуждаю на тему того, что на самом деле тестирование - это гораздо более трудоёмкая задача, чем обычно считается. И как следствие, большая часть тестов - это такая вот туфта. Либо тест заранее возвращает нужные данные, либо тестирует один-два кейса. А вариантов неправильных входящих данных ведь может быть огромное количество. То есть по-хорошему на такой заведомо сложный (и принципиально неделимый!) метод нужно десятка два тестов.

И сюда же использование для тестов БД другой системы. Например основная БД MySQL, а для тестов используется Sqlite. Тут сразу можно сказать, что это профанация. Различие даже в какой-то одной настройке БД может повлиять на результаты запроса (и теста как следствие) - а тут и вовсе используется совсем другая БД.

С другой стороны, работу с БД скорее стоит тестировать не в юнит тестах, а скажем в интеграционных. Но не будем углубляться.


Массив же "с данными, симулирующими ответ из базы данных" используется на следующему уровне, там где требуется "ответ из базы данных". Взьмём метод, который использует данные, полученные из БД. Например авторизация юзера. Этот метод должен не сам лезть в базу, а дёргать отдельный метод, вполне возможно, что совсем другого класса. И вот чтобы протестировать авторизацию, вы и мокаете метод для работы с БД, и из этого мока возвращаете тот самый массив без всякого обращения к бд.

Здесь нелишне будет напомнить название доклада с одной из последних конференций по пхп. Дословно не помню, но что-то вроде "Делайте методы как можно короче. Ваши тесты скажут вам спасибо." Собственно, именно при тестировании очень быстро начинаешь понимать удобство атомарных (то есть выполняющих какую-то одну простую операцию) методов. А без тестов пройдёт довольно много времени, пока не понадобится этот длинный метод отрефакторить, и по итогам менять кучу кода, который его вызывает.

Так что разбивайте ваши длинные методы на мелкие, и тогда вопрос, как их тестировать, в большинстве случаев отпадёт сам собой.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы