Как писать юнит-тесты, если совсем не хочется |
20.02.2019 00:00 |
Автор: Тагир Валеев, CC BY 3.0 Всех нас на работе то и дело пытаются заставить писать юнит-тесты. Многие уже поняли, что от них один вред. Написание тестов отнимает много времени, за которое вы могли бы сделать что-то более полезное. Если тест неожиданно начинает падать, ломается сборка на сервере непрерывной интеграции, не выкатывается вовремя релиз, бизнес теряет деньги и крайним оказываетесь вы, автор упавшего юнит-теста. При рефакторинге тесты причиняют головную боль, потому что начинают падать и приходится с этим разбираться. Тем не менее злые начальники требуют больше тестов, говоря о так называемом «контроле качества». Особо хитрые менеджеры даже считают покрытие и не отпускают вас с работы, пока оно не будет достигнуто. Ваш код заворачивают на ревью, если в нём нет тестов или они чем-то не понравились. Сплошное расстройство! Что же делать? К счастью, есть способы писать надёжные юнит-тесты, которые никогда не упадут. Эти способы придумал не я, их успешно практикуют в ряде опенсорсных проектов. Все примеры, которые я приведу, взяты из реального кода. Поэтому нет причин и вам не воспользоваться тем, что уже применяется на практике другими разработчиками! Самый первый и очевидный способ: ничего не проверять в юнит-тесте. Вот простой пример:
Начальник требует стопроцентного покрытия? Отлично, протестируем, что пустой конструктор по умолчанию и тривиальный сеттер не падают с исключением. То что сеттер действительно что-то установил проверять не будем, тем более что по факту мы null перезаписали null'ом. Это надёжно, такой тест падать не должен. Слишком банально и не удаётся такое пропихнуть на ревью? Можно поступить хитрее:
Выглядит солидно, будто что-то действительно проверяется. Взглянем однако на метод containsParameterType:
Изящно, правда? Оба метода по отдельности выглядят разумно, но вместе они ничего не проверяют. Такое может прокатить, особенно если методы закоммитить по отдельности и отправить разным ревьюверам. Тем более что они в разных классах! Однако так долго не протянешь. Злое начальство заподозрит неладное, не увидев никаких ассертов в коде. Ассерты всё-таки добавлять стоит. Но, например, так, чтобы они не выполнялись. Вот грубый подход:
Цикл на 0 итераций. Такое пропустит разве что сильно пьяный ревьювер. Однако следующий вариант гораздо изящнее:
Тут уже многие ревьюверы не заметят подвоха! Оба цикла ни разу не выполняются, потому что граница — размер пустого списка. Берите на заметку. Предположим, ваш коллега десять лет назад написал тест, проверяющий, что метод кидает исключение. Сделал он это старомодным способом, через catch. Прекрасно, допишите любых новых ассертов в конец метода. Никто не заметит, что они не выполняются:
Ваши менеджеры совсем обнаглели и смотрят на покрытие не только основного кода, но и тестов? Теперь они замечают такие штуки? Ладно, и с этим можно бороться. Будем писать ассерты, которые проверяют всякую ерунду. Например, что свежесозданный объект не равен null:
Если оператор
Благодаря автобоксингу примитивный
В отрыве от контекста код выглядит вполне разумно. Ревьюверу придётся проявить истинную дотошность, чтобы заметить, что метод Ещё отличный способ ничего не проверить — написать длинное сообщение к ассерту с конкатенацией разных компонентов, а второй аргумент вообще убрать:
Видите? Кажется, раз у нас длинное-длинное сообщение, то проверяется что-то серьёзное. На самом деле проверяется, что это самое сообщение не равно null, чего не может быть, потому что конкатенация строк в джаве всегда выдаст ненулевой объект. Вообще, конечно, если хочется бросить пыль в глаза, то
А если вас поймают за руку, всегда можно оправдаться, что вы проверяли стабильность метода Если вы работаете с типом double, то самое время вспомнить про сравнение с NaN. К сожалению,
Как известно, NaN ничему не равен, даже самому себе, а потому такое сравнение всегда истинно. Также
Методы Есть ещё ряд способов, по которым я быстро не нашёл примеров. Скажем, можно использовать метод Но будьте осторожны. Начальство ни в коем случае не должно узнать про статический анализ. Иначе всё зря. Большинство упомянутых в статье способов, к сожалению, легко находятся хорошим статическим анализатором. Так что т-с-с-с! |