Как использовать TDD, если исправление включает в себя изменение подписи тестируемого метода? - PullRequest
7 голосов
/ 08 апреля 2009

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

Рассмотрим следующую сигнатуру метода:

string RemoveTokenFromString (string delimited, string token)

Как следует из названия, этот метод удаляет все экземпляры token из delimited и возвращает результирующую строку.

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

При исправлении ошибки я обнаружил, что методу требуется больше информации, чтобы он мог правильно выполнять свою работу - и этот бит информации может быть отправлен только в качестве параметра (тестируемый метод является частью статического класса) .

Что мне тогда делать? Если я исправлю ошибку, это заставит меня сменить модульный тест - это будет «правильная» методология TDD?

Ответы [ 7 ]

7 голосов
/ 08 апреля 2009

Вы попали в самую опасную ловушку в TDD: вы думаете, TDD о тестировании, но это не так. Однако попасть в эту ловушку легко, поскольку вся терминология в TDD относится к тестированию. Вот почему BDD был изобретен: это по сути TDD, но без запутанной терминологии.

В TDD тесты - это не тесты, а примеры. И утверждения на самом деле не утверждения, а ожидания. И вы не имеете дело с юнитами, вы имеете дело с поведением. BDD просто называет их так. (Примечание: BDD эволюционировал с момента его первого изобретения, и теперь он включает в себя вещи, которые не являются частью TDD, но первоначальное намерение было просто «многие люди делают TDD неправильно, поэтому используйте разные слова, чтобы помочь им сделать это правильно». )

В любом случае, если вы думаете о тесте не как о тесте, а как о поведенческом примере того, как метод должен работать, должно стать очевидным, что по мере улучшения понимания ожидаемого поведения удаление или изменение теста не только разрешено TDD, это единственный правильный выбор ! Всегда имейте это в виду!

6 голосов
/ 08 апреля 2009

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

//Up front
[Test]
public void should_remove_correct_token_from_string()
{
  var text = "do.it.correctly..";
  var expected = "doitcorrectly";
  Assert.AreEqual(StaticClass.RemoveTokenFromString(text, "."), expected);
}

//After finding that it doesn't do the right thing
//Delete the old test and *design* a new function that
//Does what you want through a new test
//Remember TDD is about design, not testing!
[Test]
public void should_remove_correct_token_from_string()
{
  var text = "do.it.correctly..";
  var expected = "doitcorrectly";
  Assert.AreEqual(
      StaticClass.RemoveTokenFromString(
          text,
          ".",
          System.Text.Encoding.UTF8), expected);
}

//This will force you to add a new parameter to your function
//Obviously now, there are edge cases to deal with your new parameter etc.
//So more test are required to further design your new function
4 голосов
/ 08 апреля 2009

Сохраняйте это простым.

Если ваш модульный тест неверен или устарел, вы должны переписать его. Если ваши спецификации меняются или некоторые спецификации больше не актуальны, ваши юнит-тесты должны это отражать.

Красный, зеленый, рефакторинг также относится к вашим модульным тестам, а не только к тестируемому вами коду.

2 голосов
/ 08 апреля 2009

Существует рефакторинг под названием Добавить параметр , который может помочь здесь.

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

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

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

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

Значение по умолчанию для параметра также может помочь, если оно доступно.

1 голос
/ 08 апреля 2009

Я бы сказал, не беспокойтесь о «правильном» / «правильном» способе ... что бы ни помогло вам быстрее приблизиться к решению.

Если вы обнаружите, что вам нужно ввести дополнительный параметр,

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

Только в тех случаях, когда добавление нового параметра может привести к миллионам ошибок компиляции, я бы порекомендовал - предпринимая это маленькими шагами ... вы не хотите обновлять всю исходную базу, прежде чем узнаете, что вам действительно не нужен третий параметр или вам нужен четвертый .. время потеряно. Так что получите новую версию метода «работает» перед обновлением всех ссылок. (Как здесь говорит Филипп)

  • записать новую перегрузку с добавленным параметром
  • Переместить код старого метода в новую перегрузку
  • Сделать старое реле перегрузки или делегировать новую перегрузку с некоторым значением по умолчанию для нового параметра
  • Теперь вы можете вернуться к выполнению поставленной задачи и получить новый тест, который станет зеленым.
  • Если вам больше не нужна старая перегрузка, удалите ее и исправьте получающиеся ошибки компиляции.
1 голос
/ 08 апреля 2009

Красный, Зеленый, Рефакторинг.

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

0 голосов
/ 08 апреля 2009

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

...