Найти тему

Ответ на глупый вопрос про unit-тесты

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

1. Первая причина очевидна – тестирование функционала. Тут много писать смысла я не вижу. Тут и фиксирование реализованного функционала в описанном виде, и самопроверка реализации задачи. Попутно надо понимать, что данные тесты можно использовать для тестирования функционала с различными входными параметрами без необходимости собирать и запускать весь проект.

2. А вот для меня вторая причина важнее. Она менее очевидна и гораздо полезнее молодому неопытному программисту. Оценка качества кода. Как тесты помогают оценивать качество кода? С радостью поясню.

а) Слишком сложный запутанный код. В основном данный параметр оценивается цикломатической сложностью. Если написанный вами тест белого сценария покрывает только 10-20 процентов кода метода – метод написан плохо. Один раз стоит задаться целью полного покрытия тестами такого метода, чтобы понять насколько большую ерунду вы написали…ну или ваш коллега.

б) Неудобные интерфейсы других методов. Приведу пример – мои коллеги любят использовать простые типы для описания входных параметров методов. Хорошо это или плохо? Вопрос не простой. Есть разные взгляды на этот подход. Но если вы во время разработки тестов будете писать моки на методы с десятком входных параметров типа int и bool – вы крайне быстро поймете что написали что-то, что вызывает боль и страдания.

в) Использование глобальных переменных, окружения или еще каких-то конструкций, явно желающих сбегать куда-то далеко за пределы метода с неясной целью. Приведу пример. Внутри слоя бизнес-логики вы обращаетесь к объекту HttpContext.Current или реализовали доступ к сессионным объектам через статические методы. И вот когда вы метод, использующий данные конструкции постараетесь покрыть тестами – окажется что контролировать поведение таких объектов сложно. Мокировать еще сложнее и в итоге написать тест становится нереально.

3. Выявление простейших багов. Хотите потратить время ревьювера и тестировщика? Ну можете конечно, но почему бы не потратить час своего времени вместо 3-5 часов других людей.

4. Документирование реализованного метода. Тесты позволяют дать пример использования вашего метода для других. Необходимость неочевидная, но вспомните как часто вы беря некую не очень знакомую библиотеку – вводите в поиск название библиотеки с добавлением слова samples. Писать полную документацию сложно и не всегда возможно, а тут у вас в руках инструмент позволяющий описать пример и заодно решить задачи выше.

5. Упрощение ревью кода. Данное преимущество работает только в командах, работающих по Agile, и где делается ревью. Слабенькое конечно преимущество, но лично мне, смотря в код теста – понятно как код работает. Порой можно даже поменять входные тестовые данные и проверить упадет ли тест или все еще даст правильные результаты.

Итак – что в итоге? Написание тестов занимает время и не мало. Может показаться, что лучше потратить это время на разработку новых задач. Но время это с гарантией будет потрачено либо на ручное тестирование, которое выявит баги, которые могли быть выявлены тестами. Или на поддержку проекта. С ростом размера проекта – шанс сломать функционал в одной части системы, дорабатывая другую часть системы, растет как на ядреных дрожжах. Хотите оставить потомкам подлянку? Ну оставьте. Но мне кажется, что оставить после своей работы функционал покрытый тестами – гораздо полезнее для развития и себя и проекта.