2010-08-30 5 views
11

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

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

Является ли эта проблема неотъемлемой частью использования насмешек, и я должен научиться жить с ней, или я делаю что-то принципиально неправильно? Пожалуйста, просветите меня :) Яркие примеры, пришедшие с объяснением, приветствуются, конечно же,.

+2

Вы должны определенно google «классицистская махинация», зарезервируйте день или два и прочитайте :). imho, оба имеют свои достоинства, и оба должны использоваться, когда ситуация требует этого. –

ответ

5

когда я создать тест, который использует макет, я записывать все звонки на конкретный макет и назначить Возвращаемые значения

Это звучит, как вы можете быть чрезмерно указанием ожиданий.

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

This answer содержит краткий пример (а также альтернативное, более подробное объяснение).

2

Если вы исправляете тесты, потому что они ломаются, вы не используете их по назначению.

Если поведение метода изменяется, в тестовой разработке вы должны сначала изменить тест, чтобы ожидать нового поведения, а затем реализовать новое поведение.

+0

Это правильно и очень кратким определением TDD, но это не меняет того факта, что вам всегда приходится дважды выполнять изменения, сначала в тесте, видеть, как он терпит неудачу, а затем в коде видит его успешным. Таким образом, это «всегда реализует дважды проблему», свойственную TDD? – nkr1pt

+0

@ nkr1pt: Да, но он не изолирован от TDD. У вас будет более или менее та же проблема в любой модели разработки, которая включает тестирование в любой форме. Просто это так очевидно в TDD. – Guffa

4

Мой опыт состоит в том, чтобы использовать mocks только в баллистических системах (под). Если у меня есть два класса, которые сильно связаны, я не издеваюсь над ними, но проверяю их вместе. Примером может быть составной и посетитель. Если я тестирую конкретного посетителя, я не использую макет для композита, а создаю настоящие композиты. Можно утверждать, что это не единичный тест (зависит от определения того, что является единицей). Но это не имеет большого значения. Я пытаюсь достичь:

  1. Запись читаемых тестов (тесты без издевательств в большинстве случаев более легко читаются).
  2. Протестируйте только сфокусированную область кода (в примере посетитель-конкретизирующий и соответствующая часть композита).
  3. Напишите быстрые тесты (пока я создаю несколько классов, в примере конкретных композитов, это не проблема ... следите за переходными творениями).

Только если я столкнулся с границей подсистемы, я использую mocks. Пример. У меня есть композит, который может отобразиться в рендерере. Я бы издевался над рендерером, если бы я тестировал логику рендеринга композита.

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

+1

Хотя я согласен с этим, многие системы достаточно мелкие в достаточном количестве, что очень мало различий между насмешками все время и насмешкой только на границах подсистемы. –

+0

В этом случае: дайте системам некоторую глубину. Четко разделяйте подсистемы! – Arne

+0

Если вы чувствуете себя хорошо, тестируя несколько классов вместе как единое целое, возможно, следующим шагом для вас является объединение этого подразделения в один класс. – Ladlestein

0

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

Смежные вопросы