Logging in Unit Tests, a Bad Practice

The following text is a partial translation of the original English article, performed by ChatGPT (gpt-3.5-turbo) and this Jekyll plugin:

Логирование является неотъемлемой частью отладки. Ну, по крайней мере, в современных высокоуровневых языках программирования и архитектурах. Тридцать лет назад, в языке ассемблера, это не было так, но сейчас это так. Иногда мы отслеживаем переменные, но редко. Чаще всего мы просто выводим их на консоль. Более того, мы не просто выводим их с помощью println или чего-то подобного для вывода на консоль; вместо этого мы отправляем сообщения в фреймворк логирования, который работает с консолью или любыми другими целями логирования, такими как файлы. Преимущество таких фреймворков заключается в том, что нам не нужно удалять логирование после завершения отладки — мы просто настраиваем фреймворк на подавление всех сообщений уровня отладки в рабочей среде. Некоторое логирование может происходить внутри модульных тестов. Может быть, мы также оставляем его там или, может быть, нет?

Вот пример (это упрощение реального модульного теста в файле CalcTest.java из Polystat, статического анализатора, над которым мы сейчас работаем):

Это Java, и я использую JUnit5+Hamcrest вместе с моей собственной системой логирования jcabi-log, которая является декоратором Slf4j, который использует Log4j для вывода на консоль.

Что здесь происходит? Есть класс Foo с методом build(), который создает XML-документ (я использую библиотеку jcabi-xml, которая является декоратором JDK DOM). Затем, в модульном тесте содержимое XML-документа выводится на консоль, и делается довольно глупое утверждение: документ не является NULL. Это глупо, потому что если бы он был NULL, уже при вызове .toString() отказывалась бы логирующая инструкция.

Я являюсь разработчиком этого кода, поэтому знаю, что происходило: мне было лень написать правильное утверждение, которое бы проверяло наличие правильных элементов внутри XML-документа. Я просто вывел его на консоль, визуально убедился в его корректности и считал это достаточным. Если бы у меня было больше времени, я бы написал гораздо лучший модульный тест (я только что внес улучшения в тесты Polystat).

Теперь XML-документ создан и затем проверяется на наличие //foo XPath внутри него. Содержимое документа будет выведено на консоль только в случае, если утверждение не выполняется. Если XML содержит требуемый XPath, консольный вывод отсутствует, что означает отсутствие шума для будущих разработчиков.

Более того, это теперь тест с одним оператором, что само по себе является хорошей практикой.

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

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

Предлагаю не оставлять подобные сообщения в нашем коде.

Translated by ChatGPT gpt-3.5-turbo/42 on 2023-12-15 at 06:47

sixnines availability badge   GitHub stars