Comments 10
Монументально. Правда половина статьи про дружбу с Reqnroll.
У меня всё проще, использую тестовый вэб хост, все неуправляемые зависимости перманентно замоканы, чтобы программист не ошибся. Бд на отдельном инстансе, потому до запуска в контейнере так и не добрался.
Стратегию очистки данных выбираю по ситуации.
Если тест происходит в каком-то "скоупе" (пользователь, тенанант и т.д.), то просто создаю новый скоуп. Мусор БД не мешает и даже полезен, т.к. чужие данные мы видеть не должны.
Если тесту нужны "общие" данные, то делают TRUNCATE CASCASE. На прошлом проекте больше 1000 тестов проходили за минуту где-то. Подход с манипуляцией транзакцией считаю пока подозрительным, нужно над этим подумать.
В пирамиду тестирования не верю, видимо пишу слишком простые простые и получается, что интеграционных тестов сильно больше, чем юнитов. Критерий простой: если удобнее через интеграционный тестить, то беру его, если через юнит, то юнит. Главное, что я уверен в том, что написал и могу спокойной спать.
Слой интеграции с неуправляемыми зависимостями пишу 1 раз, тестирую руками. С ними, как правило, проблем в эксплуатации нет.
В пирамиду тестирования не верю, видимо пишу слишком простые простые и получается, что интеграционных тестов сильно больше, чем юнитов.
Kent Dodds, автор Testing Library (ранее известной как React Testing Library), также предпочитает в основном интеграционные тесты: Write tests. Not too many. Mostly integration. Он придумал концепцию Testing Trophy в качестве метафоры для такого подхода.
Также упор на интеграционные тесты иногда называют Testing Diamond (термин более ранний, но я не смог отследить его первоисточник).
А если уходить вглубь истории, есть такой интересный нюанс с появлением термина Пирамида Тестирования:
в 2009 году Mike Cohn написал статью The Forgotten Layer of the Test Automation Pyramid, суть которой можно описать так: разработчики пишут unit-тесты, QA пишут сквозные тесты, все забывают про интеграционные тесты (в статье названы Service Tests)
в той же статье он в качестве метафоры показал Пирамиду Тестирования (Testing Automation Pyramid)
затем в 2010 году в книге "Succeeding with Agile: Software Development Using Scrum" он ещё раз представил метафору Пирамиды Тестирования
Так вот: пирамида тестирования у Mike Cohn была лишь иллюстрацией к статье, а соль статьи именно в рекомендации обратить внимание на интеграционные тесты. Но почему-то в индустрии запомнили термин Пирамида Тестирования, а про интеграционные тесты снова забыли.
Уровни тестов с точки зрения внепроцессных зависимостей
Чёткие критерии разделения уровней тестов есть у Владимира Хорикова в прекрасной книге «Принципы Unit-тестирования»
Вот уж не знаю. Мне кажется, что разумнее делить уровни тестов по границам тестируемого поведения, а не по зависимостям. Тестируете поведение одного юнита - значит, это юнит-тест. Тестируете несколько своих юнитов вместе - интеграционный тест.
То, что в тесте затрагивается внепроцессная зависимость юнита, это всего лишь нюанс с некоторыми последствиями (задержки пуска, шум в результатах если зависимость сбоит; нестабильные тесты если зависимость некорректно сбрасывается и т.д.). Причём тормоза могут быть вполне приемлемы в ряде случаев. В конце концов, поведение это вполне себе атрибут юнита, а процесс это пятью этажами выше. Или вообще на другой улице.
Как вы тестируете сервисы, использующие СУБД?
Поднимаем in-memory базу.
Как изолируете тестовые сценарии, влияющие на базу данных?
Чистим часть таблиц между сценариями.
Работает замечательно.
Зачем тестировать in-memory бд? Это даст скорость, но вы теряете возможность использовать вещи специфичные для бд. Поднять контейнер с бд сейчас не сложно, для CI поднять контейнер с тем же pg не проблема, для локальных тестов есть TestConteiners. Это позволяет использовать и проверять более сложные запросы к бд, проверять миграции, а работает это не сильно медленее, например у нас тестсет из 500+ тестов на бд проходит приблизительно 45-60 секунд.
Изоляцию данных между тестами не делаем, просто в тесте генерируем данные через AutoFixture и проверяем наличие данных данных с конкретными id сгенерированными именно в конкретном тесте
У нас какие-то разные in-memory бд, потому что в моём случае она такая же полноценная, как и на диске. То есть я под этим не подразумевал какую-то куцую базу. Точно так же запускаю на ней любые запросы.
Какая именно in-memory БД используется, если не секрет?
та же СУБД, как на проде (будь то PostgreSQL, MS SQL, MySQL)
или SQLite в режиме in-memory
или
Microsoft.EntityFrameworkCore.InMemory
или что-то иное
И речь о C# / .NET или о другой платформе?
Я не говорю, что она неполноценная, она просто другая, в ней используется провайдер отличный от того, что используется в приложении. Провайдер может генерировать не совсем такой запрос, как это делает провайдер в приложении. Когда используются стандартный SQL, то проблем как правило нет, но вот когда используется расширенный SQL, например pgSQL, различные блокировки, енумы, работа с json, вот тут могут возникнуть проблемы
Тестконтейнерс этот не так быстро как хотелось бы, но в отличии от инмемори ближе к жизни. Раз дотнет и PostgreSQL, то вы можете посмотреть в сторону https://github.com/jbogard/Respawn
Интеграционные тесты для ASP.NET Core