54 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Интеграционные тесты для Java с помощью TestContainers.

12 инструментов для интеграционных и unit-тестов в Java

12 инструментов для интеграционных и unit-тестов в Java

    Переводы , 3 июля 2015 в 21:00

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

  • Когда я должен использовать инструмент X?
  • Как я должен использовать инструмент X?

Автоматизированное тестирование — очень важная часть разработки ПО, но в блогах программистов немного постов про используемые инструменты. Эта же статья позволит вам заглянуть в мой «ящик с инструментами». Я расскажу о 12-ти библиотеках и фреймворках, которые я использую для написания unit- и интеграционных тестов, а также предоставлю ссылки на страницы, которые помогут вам понять, как их использовать.

Заглянем в мой ящик с инструментами

Перед тем, как вы сможете использовать описанные далее инструменты, вы должны настроить сборку, которая автоматически запускает интеграционные и unit-тесты. У меня есть 2 заметки по этой теме:

  • Интеграционное тестирование с Maven описывает, как мы можем настроить Maven-сборку с интеграционными и unit-тестами в разных директориях.
  • Начало работы с Gradle: интеграционное тестирование с плагином TestSets описывает то же самое для Gradle.

Теперь вы готовы взглянуть на мои инструменты поближе. Я разделил их на категории, чтобы вам было проще ориентироваться.

Итак, вот 12 инструментов, которые я использую при интеграционном и unit-тестировании.

Запуск тестов

JUnit — это фреймворк, который я использую как для unit-, так и для интеграционных тестов. Мне он очень нравится, т.к. он самый популярный, поэтому имеет множество расширений. Также, если у вас возникнут проблемы — найти решение будет несложно.

NestedRunner — расширение для JUnit, которое позволяет запускать тестовые методы из вложенных классов. Мне нравится NestedRunner по ряду причин:

  • можно заменить длинные имена методов на иерархию классов в стиле BDD;
  • можно избавиться от дублирующего кода путём перемещения его в установочные методы в нужных вложенных классах;
  • можно объявить константы во вложенных классах и связать их с тестами, которым эти константы нужны.

junit-davaprovider — расширение для JUnit, позволяющее писать параметризованные тесты с использованием TestNG в качестве провайдера данных. Это большое улучшение по сравнению с обычным способом написания параметризованных тестов, который, прямо скажем, не очень.

Дополнительно:

  • Unit-тестирование с JUnit описывает, как писать тесты с JUnit 4.X.
  • Написание «чистых» тестов: красота в маленьком размере рассказывает о решении проблем, связанных с написанием «чистых» тестов.
  • Начало работы с junit-dataprovider.
  • Возможности junit-dataprovider.
  • junit-dataprovider — альтернатива параметризованным классам JUnit описывает, как перейти от стандартных параметризованных тестов к тестам, которые используют junit-dataprovider.

Макеты, заглушки, подмены

Mockito — самый популярный фреймворк с поддержкой макетирования для unit-тестов. Мне он нравится из-за простого API, множества полезных возможностей и превосходной документации.

Greenmail — сервер электронной почты, который поддерживает SMTP, POP3 и IMAP с поддержкой SSL-соединения. Он мне нравится из-за простоты использования. Когда я искал отладочный сервер электронной почты, пересмотрев несколько альтернатив, остановился на Greenmail, т.к. он работал именно так, как мне требовалось.

MockFtpServer — библиотека, которая предоставляет две разные реализации FTP-сервера («заглушка» и «обманка»), которые можно использовать для тестирования различных сценариев. Если вам нужно протестировать код, взаимодействующий с FTP-сервером, наш выбор — MockFtpServer.

Дополнительно:

  • Справочник по Mockito — отличный пример справочной документации, которая действительно помогает.
  • Интеграционное тестирование IMAP, SMTP и POP3 с помощью Greenmail.
  • Начало работы с FakeFtpServer.
  • Начало работы с StubFtpServer.
  • Что выбрать: FakeFtpServer или StubFtpServer? Поможет решить, какая реализация FTP-сервера необходима для проведения того или иного теста.

Утверждения

Hamcrest предоставляет инструменты для написания утверждений (assertions) для unit- и интеграционнаых тестов. Я его использую вместе со Spring MVC Test Framework.

AssertJ предоставляет гибкий API для написания утверждений с полезными сообщениями об ошибках, улучшает читаемость тестового кода, позволяет превратить тесты в исполняемые спецификации, которые придерживаются нужного предметно-ориентированного языка.

Дополнительно:

  • Учебник по Hamcrest.
  • Использование Hamcrest в тестировании рассказывает, как использовать Hamcrest для написания тестов, а также как расширить его возможности с помощью пользовательских модулей.
  • Обзор AssertJ Core.
  • Превращаем утверждения в предметно-ориентированный язык рассказывает, как создавать пользовательские утверждения в AssertJ.
  • Пишем чистые тесты: замена утверждений предметно-ориентированным языком. Рассказывает, почему мы должны заменить стандартные утверждения JUnit собственными, которые используют верный предметно-ориентированный язык.

Тестирование кода доступа к данным

H2 — быстрая БД, полезна для написания интеграционных тестов, которые запускаются на локальной машине разработчика.

DbUnit — расширение для JUnit, которое может быть использовано для инициализации БД в известное состояние перед выполнением каждого интеграционного теста и заполнения БД нужными данными. У DbUnit есть свои недостатки, но это очень полезный инструмент, позволяющий разделить тестовые данные и тестовый код.

Дополнительно:

  • DbUnit Core Components описывает ключевые компоненты DbUnit, знание которых необходимо для написания тестов с использованием DbUnit.
  • Лучшие практики DbUnit предоставляет пять правил написания лучших тестов для кода доступа к данным.
  • Написание тестов для кода доступа к данным поможет вам писать детерминированные тесты доступа к данным, которые проверяют нужную вещь, легкочитаемые и поддерживаемые.

Тестирование Spring приложений

Spring Test — швейцарский нож для написания автоматизированных тестов. Он предоставляет первоклассную поддержку написания unit- и интеграционных тестов для приложений, использующих Spring.

Spring Test DbUnit — интегрирует DbUnit во фреймфорк String Test. Если вам нужно написать тесты доступа к данным для приложения, использующего Spring и реляционную БД, то Spring Test DbUnit вам в помощь.

EasyJava

Java в примерах для начинающих

Главное меню

Навигация по статьям

Интеграционное тестирование и Spring JDBC

Почти все примеры в статьях и о JDBC и о Spring JDBC были написаны по одному шаблону — подготавливаем структуру базы данных, наполняем её тестовыми данными, исполняем какой-то код на тестовых данных, очищаем базу данных. В статье о признаках хорошего теста я писал, что так устроен практически любой тест: подготовка тестовой среды, выполнение теста, очистка тестовой среды.

Конечно, примеры использования Spring JDBC из моих статей нехарактерны для кода, встречающегося в дикой природе, но зато интеграционные тесты обычно так и выглядят. Spring JDBC конечно спасает, когда тесты исполняются на встроенных базах данных, но он не может выполнять скрипты для внешних баз данных и управлять их жизненным циклом.

С другой стороны, Spring JDBC предоставляет утилиты, упрощающие разработку интеграционных тестов для кода, работающего с базами данных.

Подготовка

За основу я взял код из примера «Запросы в Spring JDBC» и немного его изменил. В первую очередь, встроенная база H2 заменена на PostgreSQL:

Кроме того, я подготовил пустую базу в PostgreSQL сервере:

SQL скрипты, которые создают структуру базы и наполняют её данными, я разбил на отдельные скрипты создания каждой таблицы и отдельные скрипты для наполнения этих таблиц данными.

Выполнение SQL скриптов.

Класс ResourceDatabasePopulator позволяет выполнять SQL скрипты в указанном порядке. Звучит просто, но реально это очень мощный механизм для работы с данными. Его можно применять как в тестах, так и в каких-либо пакетных операциях над базой и вообще по любому поводу.

Я с его помощью буду инициализировать таблицы для интеграционного теста:

ResourceDatabasePopulator принимает SQL скрипты как экземпляры класса Resource , который скрывает истинный источник данных и позволяет использовать файлы из classpath, файлы из файловой системы, напрямую из интернета, байтовые потоки и т.д. Скрипты выполняются в порядке выполнения. Кроме задания списка скриптов можно задать условия их выполнения: разделитель запросов, символы комментирования, игнорирование ошибок и прочая. Готовый, сконфигурированный DatabasePopulator можно исполнить на базе данных с помощью статического метода execute ( ) класса DatabasePopulatorUtils . Метод execute ( ) ожидает получить объект DataSource , а не JdbcTemplate в качестве ссылки на базу данных.

JdbcTestUtils

Второй вспомогательный класс имеет название, намекающее, что он ориентирован только на тесты. В основном он ориентирован на очищение базы данных после теста.

В данном случае он удаляет таблицу customers, создаваемую скриптами в методе setUp ( ) . Размещение инициализации/деинициализации в методах @Before / @After гарантирует, что каждый тест класса получит одинаковый набор данных, заданный скриптами.

Автоматическое выполнение скриптов

Если внимательно присмотреться к коду setUp ( ) выше, видно, что вообщем-то для разных тестов он будут отличаться только списком скриптов, а в остальном будет тот же самый. Spring JDBC позволяет не повторяться и не копипастить ResourceDatabasePopulator из теста в тест, а указывать набор скриптов в качестве метаданных теста или тестового класса.

Аннотации @SqlGroup и @Sql говорят Spring test framework, что перед запуском каждого теста (поведение по умолчанию) или после завершения каждого теста (если указан параметр executionPhase = Sql . ExecutionPhase . AFTER_TEST_METHOD ) необходимо выполнить скрипт/группу скриптов. В примере выше перед запуском каждого теста выполняются два скрипта, которые создают таблицу и наполняют её данными. А после выполнения тестов запускается sql скрипт, удаляющий таблицу.

И опять JdbcTestUtils

В примере выше в тестовом методе используются два новых метода JdbcTestUtils . Вначале метод JdbcTestUtils . deleteFromTables ( ) очищает таблицы, не удаляя их. Затем, после того как операции над базой выполнены, метод JdbcTestUtils . countRowsInTable ( ) подсчитывает текущее количество строк в таблице. Результат подсчёта сравнивается с эталоном.

Оба метода имеют компаньонов, JdbcTestUtils . deleteFromTableWhere ( ) и JdbcTestUtils . countRowsInTableWhere ( ) , которые позволяют указать условия для выполнения операции. Кроме того, метод JdbcTestUtils . deleteFromTables ( ) принимает несколько аргументов, позволяя очистить несколько таблиц сразу. Таким же поведением обладает и JdbcTestUtils . dropTables ( ) из примера с @Before / @After , который так же способен удалить несколько таблиц.

Всё вместе.

Всё перечисленное выше можно комбинировать. Например таблицы можно создавать скриптом, а удалять в @After методе.

Интеграционные тесты для Java с помощью TestContainers.

Резюме: хоть Maven и является инструментом, стандартизирующим структуру проекта и его сборку, однако он с крахом провалил стандартизацию разного рода тестов. Ща разберем полеты.

Итак, почему же все-таки Maven не справляется со стандартизацией тестов, ведь:

  • Выполняются на фазе test
  • Лежат в src/test каталоге
  • Названия тестовых классов содержат слово Test
    • Выполнаются на фазе integration-test
    • Лежат в src/test
    • В их имени должны быть буквы IT обозначающие собсно IntegrationTests.

Проблем на самом деле с этим несколько:

Фаза integration-test выполняется после модульных тестов, это значит что отдельно их не запустить. Каждый раз когда мы запускаем интеграционные тесты, выполняются модульные. Однако обычно мы хотим запустить модульные тесты один раз, а затем отдельно запускать интеграционные. Выходит чтоб модульные тесты не выполнялись нам нужно пропускать их с помощью -DskipTests , затем окажется что интеграционные тесты тоже не запускаются потому что failsafe плагин использует под собой surefire, начнется геморрой с созданием профилей и в конце концов начнет казаться что все это слишком сложно. Кстати, почему нам важно запускать тесты раздельно:

Разработчики могут быстро получить “зеленый” фидбек и продолжить работать. Именно модульные тесты способны быстро дать базовый ответ.

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

Читать еще:  Руководство по контролю учетных записей пользователей (UAC)

Интеграционные тесты медленные, в зависимости от длительности их можно запускать по каждому коммиту, раз в день и т.п. Они тоже могут дробиться на более мелкие группы тестов, например, основные Smoke тесты выполняются первыми, затем регрессия, затем приемочные, затем какие-нибудь нагрузочные и т.п. Их удобно разделять потому что мы точно будем знать что сломалось. А также мы можем запускать отдельно определенную группу тестов и не ждать 4 часа чтоб прошло все.

Мы можем хотеть запускать одни и те же системные несколько раз. Например, мы их прогнали по текущему коммиту, а затем еще по тому что был неделю назад для того чтоб увидеть разницу между результатами.

Для системных тестов часто нужно подготовить окружение прежде чем их запускать.

Стандартно failsafe использует каталог src/test , а нам редко когда нужно помещать интеграционные и модульные тесты и ресурсы в одни и те же пакеты.

Фаза integration-test запускается перед install каждый раз. Мы же не хотим запускать медленные интеграционные тесты каждый раз когда устанавливаем артефакто в локальный репозиторий.

К сожалению для большинства разработчиков существуют лишь модульные, интеграционные тесты и “то, что делают QA”. Однако на самом деле тесты разделяются как минимум на модульные, системные и компонентные в зависимости от масштабов. Также есть функциональные и нефункциональные тесты и т.п. Более подробно можно с видами тестирования ознакомиться в одноименной статье. Но что главное – мы можем захотеть разделить все эти тесты. Для одних нужно поднимать все приложение, для других – лишь часть, для третьих вообще одного класса хватит. Однако Maven их никак не различает и не разделяет, у него есть либо модульные, либо интеграционные.

В общем подумав немного можно прити к выводу, что раз стандартный механизм Maven настолько несовершенен и все равно не сможет поддерживать всего нужного, мы можем отойти от него. Вместо этого предлагаю использовать plain old surefire plugin. Да, этот плагин заточен на написание модульных тестов, однако они по факту ничем не будут отличаться от “немодульных” – те же JUnit/TestNG будут описывать всю их логику (хотя тут позволяется также использовать всякие BDD фреймворки навроде JBehave, однако не о них речь).

Так вот как же это будет выглядеть. Для каждого из видов тестирования мы будем создавать а) профиль б) каталог с исходниками и ресурсами. Конфигурироваться же Maven будет следующим образом:

Заметьте, что в относительно небольшом куске конфигурации мы описали 3 вида тестов и все они находятся в разных каталогах:

Модульные: mvn test

Компонентные: mvn test -Pcomponent-test

Системные: mvn test -Psystem-test

Структура каталогов тогда такая:

Правда системные тесты как правило имеет смысл выделять в отдельные модули, ато и проекты.

Единственное в чем я слукавил: фаза интеграционных тестов делиться на несколько шагов и это позволяет нам сначала поднять окружение, а затем его остановить. Подход с surefire такого не даст, вам придется вручную запускать окружение с помощью явно указанных команд. Однако:

Если нам нужно полностью развернутое окружение, то это не всегда возможно автоматизировать без написания скриптов, что значит что в большинстве случаев все равно придется руками дергать их

Сложность в конфигурировании разного рода тестов перекрывает сложность запуска какого-нибудь tomcat:start

Т.к. обычно системные тесты выносят в отдельные модули или проекты, то там вполне можно использовать фазу integration-test как единственную, которая запускает тесты.

Но если вам правда хочется удобным образом автоматизировать развертывание окружения, возможно вам будет лучше сконфигурировать integration-test фазу для этого.

JUnit Categories, TestNG Groups

Последнее о чем стоит упомянуть – это JUnit категории и TestNG группы. Они позволяют с помощью аннотаций как-то помечать тесты. Однако если в TestNG это хоть как-то можно сделать удобно, то в JUnit это сделано через прямую кишку и вам придется конфигурить много профилей, у вас не выйдет задать exclude=IntegrationTest по умолчанию, а затем через командную строку активировать какие-то другие категории, для этого вам придется все равно создавать профили, а значит никакого удобства такой способ не принесет. Раз не выйдет это использовать с JUnit’ом, значит не имеет смысл стандартизировать такой подход.

  • byСтароверъtestingmaven

3Comments

Максимум 3000 символов в коменте, поэтому пришлось разбить комментарий:

Проблема выявлена правильно но решена не теми средствами, профили здесь использовать ошибочно потому как:

Теперь нельзя в сборке запустить одновременно и юнит и интеграционные тесты, а между прочим такой сценарий сборки является самым распространненым, сборка на билд сервере должна осуществляться прогоном всех тестов, да и причина по которой мы можем захотеть запустить интеграционные тесты не запуская юнит тесты может быть только одна: в коде нет проблем, интеграционные тесты не выполнились потому что мы подготовили плохой тестовый набор, например не накатили апдейт схемы на базу, или подготовили неправильные датасеты для dbunit. А вот если интеграционные тесты нашли реальную ошибку в коде то их уже не в коем случае нельзя запускать без юнит тестов потому что, во первых у нас большая проблема в юнит тестах, они неполные потому как прошляпили ошибку, второе сама процедура исправления ошибки при agile такова что сначала нужно написать юнит тест выявляющий факт того что ошибка есть а уже потом вносить исправления в код. Ситуация когда мы хотим запустить юнит теста не запуская интеграционые это да, она реальна и я покажу ниже как её обойти.

Непонятно как это всё будет выглядеть в IDE, при предлагаемом подходе у нас будет одновременно под контролем компилятора и других валидаторов только одна папка с тестами, допустим правим код и юнит тесты и не видим что код интеграционных тестов больше не компилируется.

Теперь как я обыно разношу юнит и интеграционные тесты по разным фазам:

Интеграционные тесты просто ложим в паект integration и они не дергаются на фазе юнит тестирования, как собственно и на оборот. Как видно по дефолту юнит тесты запускаются всегда, что вроде бы логично, но мы можем их пропустить выставив property skip.unittest в true если нам надо.

P.S. Как видно было использовано кунгфу по запуску одно и того же плагина на нескольких фазах, таким образом нетрудно догадаться что мы можем иметь не только две но даже больше фаз тестирования в своем проекте, например юнит, интеграционные, функциональные, приемочные просто сконфигурировав плагин на запуск в разных фазах.

Если всё таки хочется решать проблему именно через профили и никак иначе, например конкретно в вашем проекте по каким-то причинам это обоснованно, то выгоднее манипулировать элементом ‘includes’ вместо элементов ‘testResources’ и ‘testSourceDirectory’, так как перед нами изначально стоит проблема какие тесты запускать, элемент ‘includes’ даёт прямой и однозначный ответ на поставленный вопрос не мешая при использовании IDE компилятору проверять код тестов, а валидаторам ресурсов проверять тестовые ресурсы.

Integration Testing for Java EE and MicroProfile Apps With Testcontainers

Have you ever toiled with creating mock objects for unit tests? How about custom setup steps for integration tests? Ever had an issue in production because o.

Join the DZone community and get the full member experience.

Have you ever toiled with creating mock objects for unit tests? How about custom setup steps for integration tests? Ever had an issue in production because of differences in behavior between testing and production environments?

If you answered yes to any of these questions, answer one more for me: do your applications run in Docker containers?

One of the great benefits of Docker is that we get a nice consistent package that contains everything down to the OS, meaning it’s portable to any hardware. Great, so let’s use this to get consistent testing environments too!

Introducing Testcontainers

Testcontainers is a great open source library that essentially wraps Docker in a Java API, and has first-class integration with JUnit. It is mainly used for external resource dependencies and has first-class support for many popular databases such as Postgres and MySQL. However, one of the most important features is generic support for any Docker image.

Using the GenericContainer API, we can get a running Liberty server for our integration tests in no time, with no special setup required.

For example, take this JUnit test class:

In the SampleTest class above:

  • The String parameter “open-liberty:microProfile2” is the name of the Docker image to use.
  • JUnit’s @ClassRule on any Testcontainer container object results in the container being started before any @Test methods run and then stopped after all tests are done running.
  • Using withExposedPorts(9080) exposes the container’s 9080 port (Liberty’s default HTTP port) to our JUnit process.

To start using Testcontainers, simply add a test-scoped Maven dependency:

Also, if you don’t already have Docker installed on your machine, you will need to do so.

Follow Along!

All of the code in this blog post is available on GitHub. Simply clone the repo and follow the steps in the README to run it locally.

Testing My Application’s Container

Being able to start a Liberty container easily from a JUnit test is ok, but we need to get our test application in the container too. Since I am already putting my application in a Docker container, I have this Dockerfile on-hand already.

Dockerfile

Also, I’m already using some sort of Maven or Gradle plugin to package (and possibly run) my app’s container. In my case, I use the com.avast.gradle.Docker-compose Gradle plugin to build a Docker image locally. Using this Gradle plugin, I can simply invoke ./gradlew composeBuild and it will build a Docker container with everything needed to run my app in it. Likewise, I can do ./gradlew composeUp to run my Docker container locally.

Suppose the above Dockerfile creates an image named my-service when built. Using that image, we can easily test it using a GenericContainer :

Waiting for Container Readiness Before Starting Tests

Containers take a varying amount of time to be ready. By default, Testcontainers will wait for the first mapped network port to be ready. However, for application servers, the HTTP port may be available before the app is, so we want to wait for the app’s endpoint to be available before we start running tests. To accomplish this we use waitingFor(Wait.forHttp(“/myservice”)) , which will wait for http:// : /myservice to return HTTP 200 before allowing any tests to run. There are many different ways to customize container readiness checks. Refer to the official Testcontainers documentation on this topic for full details.

Port Assignment

It’s worth pointing out that when we call GenericContainer.withExposedPorts(port) , we are exposing ports from the perspective of the container. From the perspective of the test client (i.e. where the pingApp() test method runs), the Liberty container will be running on a random port. Testcontainers will randomly assign a free port on the host network, so that you don’t ever need to worry about port conflicts.

Читать еще:  Приложение gmail остановлено что делать?

Tests are going to fail at some point, and when that happens you want to be able to rely on logs generated during the test to debug the failure. Using Testcontainers built-in Slf4jLogConsumer , we can pipe all of the container output to the JUnit process so we have a single set of logs to look at. This is extremely handy when writing new tests or debugging a test failure. If you want to keep the logs separated, that’s also possible by using standard logging configuration (e.g. log4.properties).

Simple HTTP Invocations With a Typesafe REST Client and JSON-B

At this point, we can easily start our app in a container as part of the test life cycle. Now we need a good way to drive HTTP test requests on it. This is where a lot of other testing frameworks fall short in my opinion, but with a few test-side dependencies we can really smooth this out.

Let’s assume we want to test the following basic CRUD JAX-RS endpoint that manages data about people and uses the JSON format to serialize data.

The data model for a person might look like this:

JSON-B Data Class

and the JAX-RS endpoint might look like this:

JAX-RS Endpoint

Leveraging Application Classes to Simplify Test Client Invocations

If we have the application classes under test on the test client’s classpath, we can do two interesting things:

  1. Build a typesafe REST client for invoking operations on PersonService
  2. Use JSON-B to automatically convert between Person objects and JSON data.

This is made possible by the following test-only dependencies:

With these test dependencies, we can create and use a typesafe REST client like this:

Adding in a Real Database

Chances are that in production we would want our PersonService to be persisting information into some sort of database. With Testcontainers, we can easily create a database instance for our app to communicate with. In this case, I’ll use MongoDB, which does not have a first-class integration with Testcontainers, but is still easy to use as a GenericContainer .

To accomplish this, we can start by adding another container for MongoDB:

With this setup, the test client can communicate with the MongoDB container and the Liberty container. However, the MongoDB and Liberty containers cannot communicate with each other, since they are in isolated networks.

By default, each container gets an isolated network. If our containers need to communicate with each other we can enlist them in a Testcontainer Network to establish communication between the two or more containers.

The network can be visualized as follows:

We can also set environment variables on a GenericContainer — exactly as you would do in production with your containers. In this case, the application reads the MONGO_HOSTNAME and MONGO_PORT environment variables (using MicroProfile Config) to configure the MongoDB client.

Putting it All Together

Even though Testcontainers was originally intended for setting up external resources, I have found it to be extremely useful for testing my application’s code in a Docker container as well. Especially if you are already packaging your application into a Docker container, writing integration tests with this approach is very simple, and can be done in pure Java.

Once we have the container rules set up in our test class, we can write lots of simple JUnit tests that invoke HTTP requests on the Docker container:

Try it Out!

All of the code in this blog post is available on GitHub. Simply clone the repo and follow the steps in the README to run it locally.

Тестирование программного обеспечения

Основная информация

Тестирование программного обеспечения — процесс исследования, испытания программного продукта, имеющий две различные цели:

  • продемонстрировать разработчикам и заказчикам, что программа соответствует требованиям;
  • выявить ситуации, в которых поведение программы является неправильным, нежелательным или не соответствующим спецификации

Стена группы

Тестирование LLVM

Когда программа достигает определённого размера, можно гарантировать, что она слабо специфицирована и не может быть полностью понята одним человеком. Это подтверждается по много раз в день людьми, которые слабо осведомлены о работе друг друга. Программа имеет множество зависимостей, включая компилятор, операционную систему, библиотеки, каждая из которых содержит свои собственные баги, и всё это обновляется время от времени. Более того, ПО обычно должно работать на нескольких разных платформах, каждая из которых имеет свои особенности. Принимая во внимание большое количество возможностей для неверного поведения, почему вообще мы можем ожидать, что наша большая программа будет работать так, как ожидается? Одна из самых главных вещей, это тестирование. Таким образом, мы можем убедиться, что ПО работает так, как нужно в любой важной для нас конфигурации и платформе, и когда оно не работает, найдутся умные люди, которые смогут отследить и устранить проблему.

Строгая типизация в нестрогих тестах

Уже больше 10 лет _большая_ часть моей работы — чистый JavaScript. Но иногда приходится заниматься и чуть более типизированными языками. И каждый раз после такого контакта остается странное чувство «непонятности», почему же в js вот так же сделать нельзя.

Особенно потому, что можно. И сегодня мы попробуем добавить немного типизации в самую хаотическую область javascript — mock-и в unit-тестах.

Настройка системы WEB — тестирования на основе headless chromium-browser, chromedriver, nightwatch и node.js на Ubuntu

Привет, Хабр! Данная задача возникла у меня с проблемой, которая заключалась в создании робота для авторизации в Instagram, который бы делал за меня лайки. Всю задачу не напишу, напишу только часть реализации в виде настройки необходимого инструментария на удаленном сервере.

WEB — тестирование — это объемная и неоднозначная сфера, которая может заключаться в решении задач не только в плане тестирования WEB — приложений, но и, к примеру, в плане построения парсеров, роботов IoT и ботов работы с социальными сетями и все это используя только JavaScript!

Возможно, что вам не нравится словосочетание «тестирование», возможно, отчасти, из-за того, что это словосочетание заключает в себе более интересные вещи, которые, к примеру, позволят нам написать бота, способного авторизироваться в Instagram, Facebook и совершать там ряд действий от нашего лица и в одно и то же время нудно заниматься наблюдением, как выполняется наш фронтенд, но тестирование имеет смысл и уже стандартизировано сообществом
W3C и продолжает развиваться.

Цена JavaScript

По мере того как наши сайты всё сильнее зависят от JavaScript, приходится расплачиваться за то, что мы отправляем пользователям. Иногда цена не видна с первого взгляда. В этой статье я объясню, почему полезно проявить немного дисциплины, если вы хотите ускорить загрузку и производительность на мобильных устройствах.

tl;dr: меньше кода = меньше парсинг/компиляция + меньше передача + меньше распаковка

Когда большинство разработчиков думают о расходах на JavaScript, они размышляют о времени скачивания и выполнения. Отправка большего количества байт JavaScript занимает тем больше времени, чем тоньше канал с пользователем.

Это может стать проблемой даже в странах первого мира, поскольку
эффективный тип сетевого соединения у пользователя необязательно 3G, 4G или WiFi. Вы можете сидеть в кафе с WiFi, но быть подключённым к хотспоту через сотовую связь со скоростью 2G.

Интеграционные тесты для Java с помощью TestContainers. Меньше безумия, больше порядка, и всё это автоматически

На Хабре совсем нет информации про TestContainers. На момент написания этой статьи, в поисковой выдаче есть анонсы наших же конференций, и всё. Между тем, в проекте на GitHub у них уже более 700 коммитов, 54 контрибьютора и 5 лет истории. Похоже, все эти пять лет проект тщательно скрывался спецслужбами и НЛО. Настало время выйти из тени на свет.

Чукча — читатель, а не писатель. Поэтому, вместо написания своего текста, я попросил разрешения на перевод соответствующей статьи из блога RebelLabs.

Итак, здесь мы поделимся парой слов о наимоднейшей Java-библиотеке для интеграционного тестирования — TestContainers. Кроме этого, будет немного о том, почему интеграционное тестирование настолько важно для ZeroTurnaround и их требования к интеграционным тестам. И конечно, будет полнофункциональный пример интеграционного теста для Java-агента. Если кто-то никогда в глаза не видел код Java-агента, то сейчас самое время. Добро пожаловать под кат!

«Угнать за 60 секунд» на примере одного каршеринга

«Без разочарований не ощутишь вкус победы» © Мемфис Реймс

История началась банально. В каком то ролике на YouTube рассказывали про каршеринг. С демонстрацией функции «приветствия», когда вам не удается найти автомобиль на большой парковке. У меня тут же возникла мысль проверить — а не смогу ли я активировать функцию приветствия на абсолютно все автомобили этой компании?! Ну весело же. Крупный российский город. И в какой то момент тысячи автомобилей по команде начинают сигналить и моргать фарами. Почти как в фильме «Крепкий Орешек 4».

В результате все получилось куда интереснее. Ведь фактически я нашел возможность угона любого автомобиля.

Обзор программы Heisenbug 2017 Moscow: сколько нужно тестировщиков, чтобы запустить тесты на атомной электростанции?

Как вы уже, наверное, знаете, 8-9 декабря в Москве пройдёт очередной Heisenbug, поэтому мы решили познакомить Хабр с программой предстоящего события.

Но не так быстро! В качестве вступления — небольшая история из жизни. В конце вступления будет один мозговзрывающий факт насчёт этого хабрапоста. Сразу за ним — подробное изложение программы.

Почему тебе, дорогой хаброжитель, вообще стоит слушать какого-то маркетолога, который пишет эту статью? Что он может понимать в нашем нелёгком труде? За этой инфой пришлось лезть в самые тёмные глубины LinkedIn: когда-то давно, в 2010 году я устроился в одну небольшую уютную компанию в Новосибирском Академгородке на первую свою работу Java-программистом. Чтобы немножко изучить продукт, руководство поручило ответственную миссию: вручную бегать по интерфейсу нашего веб-приложения, прокликивать кнопочки и выдергивать оттуда ошибки. Довольно скоро мне поручили придумывать тест-планы, а потом и вовсе дали невероятно ответственную задачу: написать совершенно новый фреймворк для автоматического тестирования.

Особенности ручного тестирования в ALM Works и Одноклассниках

Если программирование, как утверждает известная шутка, — это процесс внесения ошибок в кодовую базу проекта, то должны быть и супергерои, не жалеющие нервов и глаз своих, чтобы число багов и недоработок не зашкаливало слишком уж сильно. Эти люди живут среди нас, и, поверьте, близко к сердцу воспринимают каждое дурное слово, сказанное по поводу очередного проявившегося в той или иной программе бага: это значит, что их работа не закончена, что их крестовый поход против поиск проблем продолжается.

Читать еще:  Забыл графический код на телефоне что делать?

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

Ради такой темы мы пригласили к общению двух специалистов в области тестирования: Никиту Макарова, занимающегося тестированием в Одноклассниках, и Юлию Атлыгину, отвечающую за то же направление в ALM Works.

Jest и Puppeteer: автоматизация тестирования веб-интерфейсов

Эту статью написал программист из Италии Валентино Гаглиарди. Он говорит, что сразу после выхода Puppeteer его заинтересовала автоматизация тестирования веб-интерфейсов с использованием данной библиотеки и Jest. После этого он приступил к экспериментам.

Здесь речь пойдёт об основах работы с Puppeteer и Jest на примере тестирования веб-формы. Также тут будут рассмотрены особенности использования Chromium с пользовательским интерфейсом и без него, и некоторые полезные мелочи, касающиеся различных аспектов тестирования веб-страниц и организации рабочей среды. Валентино полагает, что, хотя Puppeteer — инструмент сравнительно новый и его API вполне может подвергаться изменениям, у него есть шанс занять достойное место в арсенале веб-разработчиков.

Когда стоит переходить к автоматизации тестирования

В этот раз мы поговорили об автоматическом тестировании с Аланом Пейджем, приложившим руку к созданию Windows 95, Internet Explorer и MS Office. Алан — великолепный специалист и собеседник. В этом интервью он простым и доступным языком рассказывает о нетривиальных аспектах процесса. Мы сконцентрировались на вопросах определения границ между разработкой и тестированием, проблемах с легаси, оценке качества тестов и отличии тестирования крупных проектов от малых.

Dive into ICO

В статье мы рассмотрим технические аспекты подготовки и проведения ICO. Это продолжение статьи моего коллеги «Технические особенности проведения ICO. Начало», и здесь мы поговорим подробнее о некоторых технических вопросах, связанных со смарт-контрактами сети Ethereum.

Будни тестировщика, или при чем тут Пирамида Маслоу

С некоторых пор в Яндекс.Деньгах все продукты состоят из множества микросервисов, для которых выходит до десятка обновлений в день. Кроме того, регулярно приходится проверять на прочность весь платежный сервис – насколько он выдерживает пиковые нагрузки, есть ли запас прочности.

Именно поэтому подразделение тестирования ПО у нас одно из самых многочисленных. Среди тестировщиков больше всего специалистов-функциональщиков. В этой статье я на примерах расскажу, чем занимаются эти ребята и какие инструменты используют в работе.

Нагрузочное тестирование, история автоматизации процесса

Привет, Хабр! Я работаю системным администратором, совмещая это дело с организацией и проведением нагрузочного тестирования для различных проектов (как игровых, так и не очень). Так уж получилось, что нагрузкой занимается только один человек (это я).

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

Сам процесс нагрузочного тестирования в своём сознании я делю на несколько этапов:

Топ 10 инструментов автоматизации тестирования 2018

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

Не так давно свет увидел
World Quality Report 2017–2018 (Мировой стандарт проверки качества), выпущенный благодаря совместному труду сразу нескольких крупных компаний (Capgemini, Sogeti и Micro Focus), в котором было отмечено ряд интересных трендов в разработке и тестировании программного обеспечения. Авторы этого отчета считают, что основные направления в развитии разработки ПО заключаются в постоянном совершенствовании автоматизации тестирования и повсеместном применении гибких и DevOps-методологий (методология, которая объединяет в себе работу программистов и системных администраторов). Так, в данном отчете указано, что компаниям необходимо внедрять интеллектуальную автоматизацию и смарт-аналитику, для того чтобы ускорить процессы принятия ключевых решений и валидации продукта. Благодаря таким нововведениям компании смогут более эффективно справляться с тестированием интеллектуальных устройств нового поколения и высокоинтегрированных продуктов, изменения в которые вносятся постоянно. В отчете также говорится о необходимости создания интеллектуальных платформ для тестирования, характеризующихся высоким уровнем адаптивности. Благодаря таким платформам можно будет обеспечить эффективную поддержку полного жизненного цикла приложения.

Не трогайте логи руками. Часть 2: как мы внедряли Unified Logfile Analyser

В прошлой статье мы рассказали о созданной нами системе под названием
ULA (Unified Logfile Analyser) — анализаторе, основными функциями которого являются сбор и агрегация входящих сообщений об ошибках c использованием алгоритма shingles, принятие решений по ним и автоматическая нотификация при проблемах с тестовой средой. Сегодня мы поделимся практикой обнаружения/решения багов раскатки этой системы и нашими планами.

Junit: разделение интеграционных тестов и модульных тестов

я унаследовал нагрузку теста Junit, но эти тесты (кроме большинства не работающих) представляют собой смесь фактического модульного теста и интеграционных тестов (требующих внешних систем, БД и т. д.).

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

разделить их на отдельные справочники.

перейдите в Junit4 (из v3) и аннотируйте классы, чтобы разделить их.

используйте соглашение об именовании файлов, чтобы узнать, что такое класс, т. е. AdapterATest и AdapterAIntergrationTest.

3 имеет проблему, что Eclipse имеет возможность “запускать все тесты в выбранном проекте / пакете или папке”. Поэтому было бы очень сложно просто запустить интеграционные тесты.

2: рискует тем, что разработчики могут начать писать интеграционные тесты в классах модульных тестов, и это просто становится грязным.

1: Кажется, самое аккуратное решение, но моя интуиция говорит, что должно быть лучшее решение.

Итак, это мой вопрос, как вы разбиваете интеграционные тесты и правильные модульные тесты?

6 ответов

в настоящее время я использую отдельные каталоги из-за организационной политики (и наследия Junit 3), но я хочу перейти к аннотациям сам, теперь я на Junit 4.

Я бы не слишком беспокоился о том, что разработчики помещают интеграционные тесты в ваши классы модульных тестов – добавьте правило в свои стандарты кодирования, если это необходимо.

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

вы можете разделить их очень легко, используя категории JUnit и Maven.

это показано очень, очень кратко ниже, разделяя блок и интеграционные тесты.

Определите Интерфейс Маркера

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

отметьте свои тестовые классы

добавьте аннотацию категории в верхнюю часть тестового класса. Он принимает имя вашего нового интерфейса.

Настройка Модульных Тестов Maven

мы просто добавляем некоторую конфигурацию к плагину maven surefire, чтобы сделать его игнорируйте любые интеграционные тесты.

когда вы делаете mvn чистый тест только ваши немаркированные модульные тесты будут работать.

Настройка Интеграционных Тестов Maven

запустить только интеграционные тесты, используйте это:

если вы оберните это в профиль с id IT , вы можете работать только быстрые тесты с помощью mvn clean install . Чтобы запустить только тесты интеграции / slow, используйте mvn clean install -P IT .

но чаще всего вы захотите запустить быстрые тесты по умолчанию и все тесты -P IT . Если это так, то вы должны использовать трюк:

как вы можете видеть, я исключаю тесты, которые аннотируются с java.io.Serializable . Это необходимо, потому что профиль унаследует конфигурацию по умолчанию плагина Surefire, поэтому даже если вы скажете или , стоимостью com.test.annotation.type.IntegrationTest будет использоваться.

вы также не можете использовать none так как это должен быть интерфейс на пути к классам (Maven проверит это).

  • зависимость к surefire-junit47 необходимо только тогда, когда Maven не переключается на JUnit 4 runner автоматически. С помощью groups или excludedGroups элемент должен сработать выключатель. посмотреть здесь.
  • большая часть кода выше была взята из документации для отказоустойчивого плагина Maven. См. раздел ” Использование категорий JUnit” на этой странице.
  • во время моих тестов, я обнаружил, что это даже работает, когда вы используете @RunWith() аннотации для запуска наборов или весенних тестов.

мы используем плагин maven Surefire для запуска модульных тестов и плагин Maven Failsafe для запуска интеграционных тестов. Модульные тесты следуют за **/Test*.java **/*Test.java **/*TestCase.java соглашения об именах, интеграционные тесты – **/IT*.java **/*IT.java **/*ITCase.java . Так что это твой вариант номер три.

в нескольких проектах мы используем TestNG и определяем различные тестовые группы для интеграционных/модульных тестов, но это, вероятно, не подходит для вас.

Я бы перешел на Junit4 только за то, что он:)

вы можете разделить их на различные наборы тестов. Я не знаю, как они организованы в Junit3, но в Junit4 должно быть легко создать наборы тестов и поместить все реальные модульные тесты в один из них, а затем использовать второй набор для интеграционных тестов.

теперь определите конфигурацию запуска для обоих наборов в eclipse, и вы можете легко запустить один набор. Эти сюиты также смогли быть запущены от автоматизированный процесс, позволяющий запускать модульные тесты при каждом изменении источника и, возможно, интеграционные тесты (Если они действительно большие) только один раз в день или один раз в час.

используя IfProfileValue весна аннотация позволяет достичь этого без требуется плагин maven или конфигурация.

аннотировать классы или методы тестирования интеграции с помощью IfProfileValue

для запуска только с помощью модульных тестов:

для запуска с помощью интеграционного теста и модульных тестов:

кроме того, “запустить все тесты” в среде IDE будет выполняться только модульный тест. Добавить -Dtest-groups=integration аргументы VM для выполнения как интеграционных, так и модульных тестов.

нет ни одного правильного ответа. Как вы уже объяснили, есть несколько способов сделать это, которые будут работать. Я сделал как схему именования файлов, так и разделение вещей на разные каталоги.

похоже, что разделение вещи на разные каталоги может работать лучше для вас, и это кажется мне немного яснее, поэтому я склоняюсь к этому.

Я не думаю, что попробовал бы аннотации, потому что это кажется мне более мелкозернистым. Ты действительно хочешь этих двоих? типы тестов, смешанных в одном файле? Я бы не стал.

голоса
Рейтинг статьи
Ссылка на основную публикацию
Статьи c упоминанием слов: