Как научиться писать юнит-тесты, в которых будет смысл и не ошалеть от скуки?
Хочу признаться: за всю жизнь я написал меньше 10 юнит-тестов. Это при том, что люблю и часто пишу библиотечные проекты. Каждый раз перед началом проекта я говорю себе: в этот раз я буду писать юнит-тесты. Естественно, нарушаю обещание.
В оправдание могу сказать, что просто не понимаю, как подступиться к этой задаче. Допустим, я написал некий контейнер на Яве. Но чтобы хотя бы наполовину покрыть качественно различные состояния контейнера тестами, надо написать в несколько раз больше кода, чем занимает сам контейнер! А если он содержит слабые ссылки? А если он потокобезопасный? Сами тесты в этих случаях становится непросто написать. Особенно так, чтобы они были корректными.
Я вижу, что чем сложнее интерфейс, тем многократно сложнее его протестировать.
Вопрос: есть ли что-то, что существенно упрощает описанные выше проблемы. Ну, например, шаблоны тестов для тех же контейнеров. Или системы, упрощающие тестирование потокобезопасного кода. Или можно перестать беспокоиться и писать только высокоуровневые тесты? Или я что-то глобально не так понимаю?
Знакомая проблема. Хорошо писать тесты для простой функциональности. Но что делать, когда нужно тестировать не просто отдельные функции, а ещё и их комбинации? Что делать, когда количество комбинаций входных данных — огромно, или вообще бесконечно, и каждая комбинация может привести к ошибке?
Для себя нашёл частичный выход: пишу высокоуровневые тесты, а низкоуровневые заменяю множеством assert-ов. Assert проще написать, поскольку не надо воспроизводить контекст ни программно, ни мысленно — assert всегда выполняется в нужном контексте. И при запуске высокоуровнего теста фактически выполняется гораздо больше проверок, чем написано в самом тесте. Assert-ты также очень помогают в отладке — с их помощью быстрее локализуются ошибки.
Кстати, для библиотечных проектов совершенно необходимо писать и проекты, эти библиотеки использующие. Иначе — библиотека получается гарантированно ненужной. Так вот, само такое приложение и тесты к нему являются одновременно и тестами библиотеки.
Кстати, для библиотечных проектов совершенно необходимо писать и проекты, эти библиотеки использующие.
Я знаю только 2 мотивации писать библиотеку: 1) есть проект, в котором она нужна; 2) библиотека — это курсач или диплом. Во втором случае, к сожалению, ваше правило не соблюдается.
Так как вопрос в общем, то в общем уменьшение использования состояний уменьшает сложность тестирования. Например, при использовании функцонального стиля.
Попробуй почитать об TDD - Test-driven development. Это техника разработки через тестирование, которая позволить сделать процесс написания юнит-тестов частью написания кода, точнее ты будешь писать код который бы удовлетворял написанному тесту. Такая техника сделает процесс написания юнит-тестов намного интересней и эффективней, а время затрачиваемое на кодирование в целом уменьшиться, потому что уменьшиться время обычно затрачиваемое на отладку и поиск ошибок.