Pull to refresh

Comments 12

Спасибо за статью, только не совсем понятна пара моментов:

  1. При использовании аннотации TestContainers будет создаваться новый docker-container с базой для каждого тестового класса, зачем нам это? Не разумнее ли запустить одну базу для всех тестов (например из общего тестового класса осуществить BeforeAll container.start())?

  2. Почему не наполнять тестовую БД данными из какого-нибудь sql-скрипта, а не осуществлять BeforeEach repo.save()? Ведь это во-первых, лишнее взаимодействие с логикой, которое никак не проверяется, я уже молчу что в каждом классе прописать надо не забыть этот сетап..

  3. Зачем вообще осуществлять repo.deleteAll, если по умолчанию в Spring Test все транзакции и так откатываются?

  4. Зачем регистрировать username и password, если в тестовой БД будут и так значения по умолчанию "test", которые просто можно прописать в пропертях?

  5. Для тестирования API не удобнее ли пользоваться гораздо более подходящим mockMvc механизмом?

При использовании аннотации TestContainers будет создаваться новый docker-container с базой для каждого тестового класса, зачем нам это? Не разумнее ли запустить одну базу для всех тестов (например из общего тестового класса осуществить BeforeAll container.start())?

Рано или поздно — и скорее рано — продукты жизнедеятельности одних тестовых классов начнут мешать другим тестовым классам. Добавим сюда произвольный порядок выполнения тестов и то, что некоторые тесты сознательно могут тестировать некое деструктивное поведение, чреватое возникновением «мусора», и готов вывод — тестовая среда должна быть изолированной. На уровне каждого конкретного теста такая изоляция не эффективна и затратна, значит на уровне тестового класса — что и имеем.

Почему не наполнять тестовую БД данными из какого-нибудь sql-скрипта, а не осуществлять BeforeEach repo.save()? Ведь это во-первых, лишнее взаимодействие с логикой, которое никак не проверяется, я уже молчу что в каждом классе прописать надо не забыть этот сетап..

Посмотрим с точки зрения человека, который вынужден чинить покрасневший тест, который написан не им. Он смотрит в тест, и видит конкретный сетап над которым производятся тестовые действия. Если этот сетап отдельный для каждого теста, то вообще хорошо — с пределах теста ясно что делается, над какими данными делается, и какой ожидается результат. А вот «общее заполнение чем-то сторонним» — это самый большой кошмар, какой только может быть. Один тест починил — и сломал еще пяток, потому что все они не явно связаны через данные.

Он смотрит в тест, и видит конкретный сетап

И этот сетап - исполнение SQL-скрипта для популяции тестовой базы. Или такой возможности у библиотеки нет?

Это уже зависит от того, что используется в вашем проекте. Если это java+spring boot, в котором вы используете spring-data, то вы можете просто инжектнуть себе в тест бин соответствующего репозитория, и через него заполнить БД. По факту-то тест работает с реальной БД в контейнере, и работать с ней можно ровно так же, как с обычной базой. Testcontainers же это не про заполнение БД, да и вообще не про БД, а про поднять контейнер, а потом удалить его, когда нужда в нем исчезнет. А уж что в этом контейнере будет не суть важно, может кафка, а может и rabbitmq.

Спасибо.
А про связку тестового контейнера (с БД) и инструмента миграций БД (Liquibase) - не направите в нужную сторону, что и где почитать?
Т.е. концепция мне видится такой: при создании контейнера - в нём прокатываются миграции, затем - SQL для популяции тестовых данных.
Привязываться к использованию функционала тестируемого приложения (исп. репозитория и т.п.) здесь не хотелось бы. Отдельный SQL где-то в test/resources выглядит предпочтительней, на мой взгляд.

Если накат liquibase сделан отдельным джарником, который нужно отдельно запускать, то могут быть проблемы, но если он классически часть проекта, то накатится сам точно так же, как на БД развернутую обычным методом.

если имеется 1к тестов, то при их запуске 1к раз будет запускаться testcontainers с субд и liquibase миграциями? верно ли понимаю?

Если это 1к классов, то да. Если это все в одном классе, то нет.

2.5 года назад написал свою библиотеку для тех же целей на .NET и она очень успешно используется в нашей фирме. Она не такая гибкая, но достаточно легко расширяется. Тестим MySql, MongoDB, Postgress, RabbitMq, Kafka+Zookeeper, Elasticsearch (включая cross-cluster). Почитал, подумал, а может заменить на TestContainers? Но два самых важных фичера там не вижу:

1) reuse containers: там нельзя оставить в живых контейнер после теста, чтобы следующий тест бежал быстрее, а не тратил время на новый docker run + wait for readiness. У нас же есть две конфигурации Dev и CI. В Dev контейнер остается в живых и может быть использован заново. В CI тесты бегут параллельно, поэтому каждый раз поднимается новый контейнер и умирает после теста (или нескольких тестов).

2) executor: когда тестов много, они жрут много ресурсов, и много CI бегут параллельно, Docker Host не выдерживает и это сильно замедляет процесс CI/CD. А вот kubernetes решает эту проблему. У нас можно выбрать в качестве executor'а Docker или kubernetes.

Вот когда, и если вообще, эти возможности будут добавлены, наверное гляну снова. Ну а пока, работает - не трогай.

Это в Java, а .NET такого нету. Но и в Java, как я понимаю, реализация не полноценная. Если код меняется в зависимости от конфигурации, то этим нельзя пользоваться.

Sign up to leave a comment.

Articles