Pull to refresh

Comments 17

Спасибо за статью! Подскажите, пожалуйста, как быть в случае варианта «Использовать транзакции БД при применении фикстур», когда я тестирую эндпоинт, внутри которого есть свои транзакции? Ну, скажем, у меня есть эндпоинт регистрации пользователя. Там я открываю транзакцию, внутри которой делаю запись в несколько таблиц. Я так понимаю, что в таком случае вариант использования транзакций при применении фикстур уже не прокатит?
Да, это может быть проблемно, т.к., насколько я знаю, практически никакая СУБД не поддерживает вложенные транзакции.
У нас используется ORM Doctrine, который реализует вложенность на своей стороне, используя механизм SAVEPOINT.
Спасибо. Тоже использую Doctrine — не знал, что там savepoint под капотом (доку надо лучше читать и код смотреть). Огромное спасибо!
UFO just landed and posted this here

Это сработает, если окружение linux. Для macos и windows не уверен, что профит будет существенным

На Винде есть wsl, в нём все работает. Мак страдает, да. Но это страдания разработчика, в CI все будет ок. А разработчики могут запускать отдельные сьюты у себя.

Ещё можно писать не изолированные, а реалистичные тесты, когда нужное состояние создаётся не фикстурами, а пользовательскими действиями прямо на грязной базе. Тут, правда, добавляется требование запуска тестов в правильном порядке. Я рассказывал об этом подходе тут: https://m.habr.com/ru/post/510824/

Не совсем понял, ваш подход предлагает тестировать компонент начиная от дочерних к компонентам более высокого уровня в строгом порядке?

От менее зависимых к более зависимым. В том числе от менее зависимых тестов к более зависимым. Например, отдельно можно проверить создание сущности, а потом уже проверять поиск сущностей, в начале теста насоздавав несколько разных.

Мне больше всего помогла сборка контейнеров БД с данными внутри. Дропнуть и поднять контейнер- это очень быстро. Есть рецепты для MariaDB и PostgreSQL.
Но на редактирующих методах были грабли с 1С. Её я не допинал до докера. И в планах было писать моки на такие интеграции.

Предлагаете переподнимать контейнер с СУБД между тестами?
Это уж как контейнер собран. Если все фикстуры и миграции уже там, то можно и между тестами.

А если что-то нужно ещё докатывать, то всё равно может появиться желание оптимизировать.
Хорошая статья, достаточно объемлющая. Подтвержу полезность следующих (и многизх других методов):
-Несколько джоб с тестами в CI
-Фикстуры
-Контейнеризация

Хочу заметить, что в статье перечислены методы стабилизации и оптимизации сетапа и самих тестов, но не сказано о том, что в первую очередь надо понять, что именно больше всего затягивает выполнение тестов. Может замена создания тестового пользователя на инсерт фикстуры в бд и сократит время процента на 2-3%, а работу с какой-либо внешней монструозной системой оставили без внимания, хотя ее оптимизация (или изоляция) позволила бы сократить время вдвое.
Спасибо за комментарий )
В целом, да, согласен )
Замечу, что «замена создания тестового пользователя на инсерт фикстуры в бд» сделано не из-за увеличения производительности, но для того, чтобы тестировать функционал более изолировано (например, чтобы легче было локализовать ошибку: в функции создания или в функции чтения она происходит; также если тестов на чтение достаточно много, то соответственно изменение логики в создании ресурса может потребовать изменений во всех этих тестах)
Нужно также понимать, что приемы описанные в статье являются результатом нашего опыта, поэтому не могут быть универсально применены для любого приложения. Интеграция с какой-либо системой уже скорее является частью предметной области конкретной компании и как оптимизировать работу с ней могут знать только ее работники (со своей стороны я мог бы предложить только, например, переопределить компонент в DI-контейнере/сервис-локаторе (мок))
Получается, что у вас идет только проверка ответа, но то, что записалось в БД, например, никак не проверить? Раз все только в json и yml.
Я не считаю, что у меня очень сложный проект (CRM для школ), но и то, отправляя запрос на создание записи человека на обученике, мне нужно проверить не только, что запись создалась, но и что деньги списались, баланс у ученика обновился, уведомления ученику и менеджеру отправились и т.д.

Вообще, я вынашиваю идею не накатывать и не откатывать изменения после каждого теста/блоков тестов, а работать с одной базой, просто подготавливать каждый раз нужные данные и считать относительные значения. Например, есть у нас созданный юзер с id 1, мы тестируем ему добавление денег на баланс. Перед выполнением теста мы взяли из БД, сколько у него сейчас на балансе, сделали свой запрос (например, внесли 100 рублей), и после этого проверили, что баланс увеличился на эти 100 рублей. В итоге нам не интересно, что там сделали с этим юзеры другие тесты, главное, чтобы не удалили.
А если нам нужен особенный объект (удаленный юзер, или, наоборот, юзер для удаления), то мы создаем его внутри самого теста в БД.
Такой вариант рабты тестов не рассматривали?
Состояние БД после тестов у нас также проверяется. Для этого в папке с классом теста есть отдельная директория, в которой можно описать yml с ожидаемыми значениями для интересующей таблицы.

При вашем подходе не получится так, что тесты будут дублировать правила бизнес логики?
Получается, что так. Но как-то же это все нужно проверить.
Sign up to leave a comment.

Articles