Статьи

Использование JUnit для чего-то еще

junit! = юнит тест

Junit — это инфраструктура модульного тестирования Java. Обычно мы используем его для модульного тестирования, но много раз мы используем его и для выполнения интеграционных тестов. Основное отличие состоит в том, что модульные тесты тестируют отдельные модули, в то время как интеграционные тесты проверяют, как различные классы работают вместе. Таким образом, интеграционные тесты охватывают более длинную цепочку выполнения. Это означает, что они могут обнаружить больше ошибок, чем модульные тесты, но в то же время они обычно выполняются дольше, и в случае неудачи обнаружить ошибку будет сложнее. Если вы, как разработчик, знаете об этих различиях, нет ничего плохого в том, чтобы использовать junit для выполнения не модульных тестов.

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

После всего сказанного позвольте мне рассказать вам другую историю и присоединиться к двум темам позже.

Мы говорим на языках… много

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

Например, у нас есть файлы

messages-de.properties
messages-fr.properties
messages-en.properties
messages-pl.properties
messages.properties

и в коде Java мы обращались к ним через  вызов Spring  MessageSource

String label = messageSource.getMessage("my.label.name",null,"label",locale);

Мы, программисты, ленивы

Проблемы возникли, когда у нас не было некоторых переводов текстов. Работа по определению фактического текста меток на разных языках не принадлежит программистам. Программисты хорошо говорят на Java, C и других языках программирования, но не очень хороши, когда дело доходит до естественных языков. Большинство из нас просто не говорят на всех необходимых языках. Есть люди, у которых есть работа по переводу текста. Разные люди обычно для разных языков. Некоторые из них работают быстрее, другие медленнее, и кодирование просто не может дождаться готовности перевода. Пока доступен окончательный перевод, мы используем временные строки.

Все временные решения становятся окончательными.

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

Процесс и дисциплина: не удалось

Чтобы избежать этого, мы внедрили процесс. Мы открыли выпуск Jira для каждого перевода. Когда перевод был готов, он был привязан к проблеме. Когда он был отредактирован в файле свойств и зафиксирован для git, проблема была закрыта. Это было таким бременем и накладными расходами, что программисты замедлялись из-за этого, а менее дисциплинированные программисты просто не следили за процессом. Вообще это была плохая идея.

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

Light-way процесс и контроль

Проверка была бы обременительной вручную. Мы создали тесты junit, которые сравнили различные языковые файлы и проверили, что в одном из них нет другого ключа, и значения не совпадают с английской версией по умолчанию. Тест junit должен был выполняться каждый раз, когда проект должен был быть выпущен. Затем мы поняли, что некоторые значения действительно совпадают с английской версией, поэтому мы начали использовать букву «X» в первой позиции в языковых файлах, чтобы обозначить метку, ожидающую замены действительного переведенного значения. В этот момент кто-то предположил, что тест junit можно заменить простым «grep». Это было почти верно, за исключением того, что мы все еще хотели обнаружить пропущенные ключи и автоматически запустить тест во время процесса выпуска.

Резюме и вынос

Фреймворк Junit был разработан для выполнения модульных тестов, но фреймворки могут и будут использоваться не только для тех целей, для которых они были предназначены. (Примечание: это действительно так для любого инструмента, будь то простой молоток или сложный метод по умолчанию в интерфейсах Java.)

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

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