четверг, 29 мая 2014 г.

Про юнит-тесты

В последнее время модно ругать юнит-тесты, по разным причинам. Сложность поддержки в актуальном состоянии системы юнит-тестов, отсутствие 100% гарантии корректности кода в случае, если тесты проходят, использование интеграционных тестов, очень многий код сложно тестировать с помощью юнит-тестов, существование практики написания тестов тупо ради покрытия и тд.
Я не собираюсь быть адвокатом какой-либо из сторон спора, вместо этого, я хочу показать, что юнит-тесты - вещь простая и естественная, вытекающая из нормальной практики программирования.
Итак, когда опытный программист пишет код функции с нетривиальной логикой, он думает в том числе и в терминах инвариантов. Практически любой код содержит кучу инвариантов (инварианты циклов, инварианты состояния объектов и тд) и желание зафиксировать их в коде - вполне естественно. Обычно, это делается с помощью assert-ов. Assert-ом удобно проверять, например, что счетчик ожидающих обработки элементов, после выполнения цикла, будет равен нулю, либо, что указатель находится внутри массива, перед выбрасыванием исключения можно проверять - не останется ли объект после этого в невалидном состоянии, и тд и тп.
Но более сложные инварианты с помощью assert-а проверить проблематично. Здесь уже программисты часто прибегают к условной компиляции, для того, чтобы вставить дополнительные проверки в отладочный билд.
Все эти проверки засоряют код, который помимо основной логики и логики обработки ошибок, содержит теперь и кучу отладочного кода, который заботливо вырезается компилятором в релизной версии. Если написать много такого кода, то обязательно появится следующая идея - "а почему бы не вынести все это в отдельное место, чтобы оно не мозолило глаза" и появляются юнит тесты. Вот и все :)

Комментариев нет: