среда, 11 января 2012 г.

The Art of Unit Testing

imageЕсть некоторые категории знаний, которые профессиональный разработчик познает в процессе своей работы, не прилагая к этому особенных дополнительных усилий. Вот, например, мало кто из нас читал замечательную книгу по регулярным выражениям Джеффри Фирддла, чтобы познакомиться с одноименной темой. Безусловно, есть масса людей, для которых «регвыры» стали смыслом жизни и без подобных фундаментальных знаний никак не обойтись. Но в большинстве случаев пары мелких статей и справки в соответствующем разделе документации будет достаточно для более или менее комфортной работы с регулярными выражениями (если такое понятие, как «комфортная работа» с регулярными выражениями вообще существуетJ).

Аналогичным образом мы обычно относимся и к изучению юнит тестирования. Ведь юнит-тесты – это же не rocket science; для их изучения не требуется многолетняя подготовка и множество бессонных ночей проведенных за изучением толстенных «талмудов» от гуру юнит-тестирования. Концепцию автоматизированного тестирования кода можно объяснить за 10 минут, а познакомившись с одним из тестовых фреймворков семейства xUnit (еще 15 минут), вы сможете работать с любым другим фреймворком практически сразу же. Затем нужно будет потратить еще 20 минут на изучение какого-нибудь изоляционного фреймворка, типа Rhino Mocks, и, вуаля, у нас есть еще один профессионал в области юнит-тестов.

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

Забегая вперед, стоит сказать, что я заблуждался и книга The Art of Unit Testing by Roy Osherove будет полезна даже опытным разработчикам, но давайте обо всем по порядку.

Структура книги такова, что автор идет от наиболее простых и базовых понятий к более продвинутым вещам. Начинается все с простых примеров и определений, дается введение в TDD, рассказывается о «швах» приложения и об использовании «фейков», таких как моки и стабы, а также кратко описываются разные изоляционные фреймворки.

С самого начала Рой пытается вдолбить в голову читателя одну важную мысль: качественные тесты не менее важны, чем качественный production код! О том, что такое хорошие тесты, посвящена целая глава 7 The pillars of good tests, но даже за ее пределами тень «хороших» тестов будет преследовать читателя практически постоянно. О качестве кода написаны, наверное, десятки книг и бесчисленное множество статей; все мы знаем о том, как важно писать простой в сопровождении код и что делать для повышения его качества. Но к качеству тестов наше отношение зачастую не столь осмысленное, хотя плохие тесты могут испортить вам жизнь ничуть не хуже го$#о-кода в бизнес-логике.

Нет никакого смысла в написании плохих юнит тестов, если только вы не новичок в этом деле и не учитесь таким образом писать хорошие тесты. Если вы по неосмотрительности собираетесь писать плохие тесты, то с тем же успехом вы можете вообще отказаться от этого занятия. Это убережет вас от неприятностей, связанных с отставанием от графика и избавит вас от дополнительных проблем с сопровождением.

Очень здорово, что помимо принципов юнит тестирования Рой уделяет внимание и таким важным аспектам, как внедрение юнит тестирования в организации, тестирование унаследованного (legacy) кода и влиянию тестов на дизайн приложения. В вопросах дизайна Рой считает, что testable дизайн обусловлен, прежде всего, ограничениями языка или среды программирования и не существует в динамических языках программирования (поскольку там мы «замокать» можем все, что угодно). Я с таким подходом не согласен, поскольку считаю, что хороший дизайн по умолчанию хорошо тестируем, и что возможность написания юнит тестов является хорошим признаком простоты контрактов классов и признаком того, что класс не берет на себя слишком много.

ПРИМЕЧАНИЕ
Подробнее об использовании юнит тестов как «лакмусовой бумажки» плохого дизайна можно почитать в заметке “Идеальная архитектура”
.

По признанию самого Роя он потратил на написание книги 3 года - и это больше, чем он потратил на «создание» двух своих детейJ и периодически это чувствуется. Так, например, в разных местах книги используются разный формат диаграмм классов, иногда отличается наименование тестовых классов и методов, да и вообще, ощущение дежавю периодически посещает. Есть и другие мелкие замечания. Так, автор на протяжении двух сотен страниц использует стандартный синтаксис утверждений библиотеки NUnit, а с 200-й страницы, вдруг начинает использовать Assert.That и заявляет о том, что этот синтаксис более декларативен. Очевидно, что года через полтора после начала работы над книгой Рой добрался до этого синтаксиса, который ему понравился, а сил и времени на изменение предыдущих примеров уже не было.

Единственным существенным замечанием к этой книге является слабое раскрытие темы параметризованных юнит тестов. Да, Рой упоминает вскользь об этой возможности, но уж очень поверхностно и где-то ближе к концу книги. Чувствуется некоторая несправедливость, когда о том, что плохо рассчитывать на порядок запуска юнит тестов автор тратит 4 (!) страницы, а на параметризованные тесты, которые могут сэкономить массу времени и существенно повысить читабельность тестов, тратится от силы 2 абзаца.

Можно найти и другие моменты, в которых ваше мнение будет отличаться от мнения автора, но в целом, книга “The Art of Unit Testing” является одним из лучших источников информации по теме юнит тестирования, которая может либо изменить ваше мировоззрение в правильную сторону, либо обобщить и структурировать уже существующие знания.

Оценка: 4+

Дополнительные ссылки по теме
Книги
  • The Art of Unit Testing by Roy Osherove
    • Подкасты
    • Статьи
    • 9 комментариев:

      1. А Ошеров тем временем слинял на Ruby

        ОтветитьУдалить
      2. Честно говоря, жалко. Довольно интересный товарищ.

        ОтветитьУдалить
      3. Не то что бы слинял. Он обьяснил в одном из своих выступлений, что ему захотелось попробовать что то новое, дабы продолжать развиваться как разработчик. Он не отрицает возможности возвращения в стэк Microsoft. Ещё он упоминул (не вдаваясь в подробности), что вещи о которых он говорил на протяжении лет, проталкивая и надеясь увидить их реализацию в экосистеме .NET (как от Microsoft так и от ALT.NET), в мире RoR существуют как само собой разумеющиеся. Он конечно говорил в контексте TDD и UnitTesting. И вообще, что экосистема RoR лет на 5 опережает .NET.

        ОтветитьУдалить
      4. Он конечно упомянул, но судя по постам после и его твитам, о возврате речь не идет.

        ОтветитьУдалить
      5. Книги «xUnit Test Patterns: Refactoring Test Code» (Gerard Meszaros) и «Working Effectively with Legacy Code» (Michael Feathers) изданы на русском языке издательством «ВИЛЬЯМС»

        Сергей, когда книгу Скита Вам можно передать?

        ОтветитьУдалить
      6. Да, книгу «The Art of Unit Testing» можете порекомендовать для перевода на русский язык? Черкните мне в блог

        ОтветитьУдалить
      7. @Виктор Штонда: Да, книгу The Art of Unit Testing очень неплохо было бы имеь на русском. Благо она не слишком большая, да и язык довольно простой. Аудитория - довольно широкая.

        ОтветитьУдалить
      8. Прочитал недавно книгу, очень понравилась. Было как-то так:
        До: Блин, как вообще писать юнит-тесты? Все о них говорят, а толковых статей нет, ничего не понятно.
        После: Моки, стабы, тестопригодная архитектура? Это же очевидно...А ещё код, поддающийся тестированию хорошо влияет на архитектуру, даже если слаб в паттернах и проектировании в целом :)

        ОтветитьУдалить