Как стать автором
Обновить

Комментарии 14

Спасибо. Есть несколько вопросов:

  1. Зачем публиковать плагин, который нужен только вашей компании на Marketplace, когда есть Custom Plugin Repository?

  2. Рассматривали вариант не писать плагин, а воспользоваться DynamicTest и @TestFactory? Сами тесты генерировать на основе json описания.

Здравствуйте.

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

  2. Вариант не рассматривал, но суть вопроса уловил. По всей видимости, Вы о снижении кол-ва кода, которого можно добиться с помощью комбинации DynamicTest и @TestFactory. Обязательно попробую, спасибо.

Вы о снижении кол-ва кода

В конечном итоге, да.

Я мог понять задачу неправильно, но достаточно было бы директории с JSON-ами вида my.package.ClassName.json (или иерархии директорий - дело вкуса), и одной TestFactory, которая бы генерировала динамические тесты для каждого класса в рантайме.

Так и кода меньше писать (точнее вообще не надо писать, кроме TestFactory один раз). И плагин никакой не нужен (ну или action вида Create test JSON можно сделать для совсем ленивых).

Минус подхода - нет явной связи между классом и тестом в коде. Например, find usages не покажет что класс в каком-то тесте используется и разработчик может, допустим, переименовать класс, но забыть переименовать JSON. Тест потом упадёт, конечно, и проблема всплывёт, но не сразу.

НЛО прилетело и опубликовало эту надпись здесь

Спасибо за статью! У меня есть пара вопросов, которые хотелось бы обсудить, но не про плагин, а про подход.

Я часто встречаюсь с мнением, что такие тесты вооще не нужны, потому что работоспособность сериализации и десериализации постоянно проверяется QA в процессе тестирования системы и разработчиками в процессе разработки (они это через сваггер делают). Это мнение мне неблизко, но всё-таки мне очень интересно, как вы убедили разработчиков, что такие тесты нужны.

И ещё интересно как контролируется, что разработчик не забыл написать тест. Я так понимаю покрытие тут не поможет, потому что генерированный ломбоком код всё равно туда не попадает. Да и в любом случае, скорее всего геттеры и сеттеры покрываются какими-то соседними тестами. Остаётся только надеяться на то, что другие разработчики будут внимательны и не дадут смёржить пул реквест без такого теста?

Уровень покрытия, согласно Quality Gate, должен быть не менее 85%, но на самом деле, его можно было поднять и выше, т.к. зачастую покрытие не ниже 95%. Такой сравнительно высокий уровень покрытия требует определенных временных затрат.

Так что считают именно покрытие, а не забыл/не забыл. Более того думаю, что разрабы как раз покрывают тестами сериализацию только, чтобы получить заветные проценты на "дешевых" тестах, а не на сложных, где логика тестируется. Пакеджи с dto и обвязой вокруг них вообще должны игнорироваться при высчитывании покрытия, но почему-то это редко кто настраивает

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

В примере используется Lombok, его можно настроить, чтобы он ставил на сгенерированные dto анотации *Generated . Тогда jacoco проигнорирует сгеренерированный код. Затраты небольшие, специально пакеты указывать не надо. Мне кажется эту фичу часто используют

Спасибо за интересный вопрос.

мне очень интересно, как вы убедили разработчиков, что такие тесты нужны

Так как я и есть один из разработчиков - меня даже и убеждать не пришлось :). На самом деле просто слишком высока цена ошибки. Ведь API внешний, им пользуются много потребителей. Они разрабатывают своё ПО для интеграции с нами. Стоит что-то пропустить и затем либо вечно об этом помнить, чтобы никому ничего не сломать, либо долгая процедура - договориться с потребителями. Оба пути неприятные - костыли либо репутационные риски. Поэтому пока тест не написал, считай - не проверил.

Да и в любом случае, скорее всего геттеры и сеттеры покрываются какими-то соседними тестами.

Полностью согласен, покрываются соседними тестами, статический анализатор может пропустить. Да, как Вы верно сказали, остается code review.

Стоит что-то пропустить и затем либо вечно об этом помнить, чтобы никому ничего не сломать

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

Безусловно, интеграционными тестами мы также можем закрыть эту задачу.

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

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

А что должен тестировать этот тест? Какие ошибки он может поймать? Каких ошибок вы вообще в этом коде ожидаете?

Такие тесты (@JsonTest) проверяют корректность настройки Jackson’а, которую мы реализуем в соответствии с контрактом.

Пример:
Мы описываем DTO, настраиваем: 
* форматы дат (@JsonFormat);
* имена полей (@JsonProperty);
* алиасы (@JsonAlias) также иногда настраиваем для десериализации;
* DTO может использовать ENUM’ы, которые сериализуются не “as-is”, а, к примеру MALE/FEMALE должны в итоге выглядеть как мужской/женский и т.п (@JsonValue).

Когда мы все это настроили, то проверяем, что результат соответствует требуемому (согласно постановке/договоренностям) контракту. То есть результат сериализации мы сравниваем с эталонным JSON, который рассчитываем получить, а десериализации - с объектом, который из него собирается.

Это настройки пишутся один раз (ладно 3-4 раза в разных местах для учета всяких странных случаев) и меняются раз в 5 лет максимум. Изменения в стиле afterburner на blackbird заменить.

Любой объект сериализуется так как в нем написали. Логики в сериализации нет, все декларативно. Тест повторяет правила сериализации написанные в классе. При этом он менее удобен для понимания и написания. При любом изменении не включая мозг тест меняется. Я бы поменял в классе - посмотрел что вышло - скопипастил в тест.

И ради чего? Какой тип ошибок может поймать этот тест? Какую реальную ошибку он у вас поймал?

Наверное, можно ещё упростить и не делать плагин. Взять, к примеру, подход, который использован в MapStruct, он умеет генерировать код и классы. Добавляем аннотацию над Dto-классом, в аннотации имя json- файла в ресурсах, и тест автоматом генерится.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий