// codeart.ru / Вопрос/Ответ / Немного про State тестирование в TDD Форум

Немного про State тестирование в TDD rss подписка

Автор: Evgeniy Sergeev

Насколько я понимаю, в Unit тестировании существует два основных способа построения тестов: State-based testing (Тестирования состояния объекта) и behavior-base testing (Тестирование поведения объекта). Новичкам в TDD обычно предлагают освоиться с первым, а только потом переходить ко второму. В связи с тем, что TDD я изучаю не так давно, у меня возникает куча вопросов и предположений. В этом посте я хочу немного поразмыслить над Тестированием состояния объекта и по возможности получить комментарии о том, что я понимаю правильно, а что нет.

Итак, state bases testing — это такое тестирование, при котором проверяется состояние объекта. В прошлых постах я уже размышлял на тему состояний у модели, а так же о том, как они могут выражаться. Поэтому мне вроде бы понятно, что при использовании данного метода тестирования следует проверять значение набора переменных в контексте состояния объекта.

То есть, допустим, у нас есть набор состояний, каждое из которых определяется исходя из значений внутренних переменных объекта (или одной переменной — неважно). Тогда не нужно перебирать все возможные комбинации значений для этих переменных, а только проверить одну конкретную, соответствующую необходимому состоянию объекта. И вот здесь у меня возникает один большой вопрос — если у нас есть несколько промежуточных состояний, то нужно ли проверять их?

Например, я точно знаю, что для того, чтобы лед превратился в пар, он должен пройти через жидкое состояние — воду. Поэтому если тест на наличие пара проходит успешно, то можно с уверенностью утверждать, что лед находился в жидком состоянии. Но тогда не понятно, что делать если итоговое состояние объекта может быть получено из нескольких промежуточных состояний? Возможно, в таком случае стоит рассмотреть каждое из промежуточных состояний отдельно? Или нет?

И еще один момент — при тестировании состояния объекта вряд ли можно добиться 100% покрытия кода (если его вообще можно добиться). В любом случае тесты будут покрывать какое-то ограниченное количество интересующих нас состояний. А все остальные недокументированные состояния, которые по сути и являются источником проблем, останутся непроверенными. Поэтому опять же возникает вопрос: как определить минимально необходимое количество состояний, которое позволит получить более менее высокую надежность кода? Очень интересует практический опыт. Если есть, что сказать, то очень прошу поделиться своим мнением в комментариях.

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

  1. Немного о behaviour тестировании в TDD

    Лучшие комментарии

  1. «State-based testing» подразумевает не то, что ты будешь воспринимать обьект как state machine, а то, что ты будешь проверять результат работы методов постфактум.

    Например — проверить то, что ты опубликовал статью можно двумя способами:

    1. Вызвать «article.publish». Проверить, что «article.published_at == Time.now».
    2. Создать message expectation на то, что будет вызван метод «article.update_attributes» с параметром «{ :published_at => Time.now}». Вызвать «article.publish». Таким образом ты убираешь из тестирования работу с бд (и подразумеваешь, что update_attributes будут правильно отработаны), завязываешь метод publish на метод update_attributes (с одной стороны — плохо, ибо ты не сможешь потом переписать метод по-другому без изменения теста, с другой стороны — ты более явно описываешь интерфейс обьекта article).

    Также первый подход даст тебе более глубокую уверенность в работоспособности, т.к. он показывает, что всё действительно работает на всех уровнях, с другой стороны — он будет медленнее.

    Да, и во втором случае ты надеешься на то, что update_attributes протестирован и работает как надо.

  1. А может ну его нафиг, TDD? )

  2. «State-based testing» подразумевает не то, что ты будешь воспринимать обьект как state machine, а то, что ты будешь проверять результат работы методов постфактум.

    Например — проверить то, что ты опубликовал статью можно двумя способами:

    1. Вызвать «article.publish». Проверить, что «article.published_at == Time.now».
    2. Создать message expectation на то, что будет вызван метод «article.update_attributes» с параметром «{ :published_at => Time.now}». Вызвать «article.publish». Таким образом ты убираешь из тестирования работу с бд (и подразумеваешь, что update_attributes будут правильно отработаны), завязываешь метод publish на метод update_attributes (с одной стороны — плохо, ибо ты не сможешь потом переписать метод по-другому без изменения теста, с другой стороны — ты более явно описываешь интерфейс обьекта article).

    Также первый подход даст тебе более глубокую уверенность в работоспособности, т.к. он показывает, что всё действительно работает на всех уровнях, с другой стороны — он будет медленнее.

    Да, и во втором случае ты надеешься на то, что update_attributes протестирован и работает как надо.

  3. fxposter, ИМХО, идея как раз в том, чтобы представить объект как кончены автомат.
    В твоем примере четко прослеживается два состояние (наверняка их больше, но не суть): во-первых, состояние «статья не опубликована», во-вторых состояние «статья опубликована».

    Относительного второго варианта, я правильно понимаю, что это behavior-base testing?

  4. Тормоз, :-) Нет, тестирование штука полезная, только главное определить некий необходимый минимум — что тестировать, а что нет. Это как раз сложно.

Leave a Reply

« »