Модульное тестирование: «Это запах кода, если вы проводите рефакторинг, а соавторов нет»?

9

Я читаю «Искусство модульного тестирования» Роя Ошерова. Я нахожусь в разделе 7.2 Написание поддерживаемых тестов, где у автора есть эта заметка о запахе кода:

ПРИМЕЧАНИЕ. Когда вы реорганизуете внутреннее состояние, чтобы оно было видимым для внешнего теста, можно ли это считать запахом кода (признаком того, что что-то может быть не так в дизайне или логике кода)? Это не запах кода, когда вы реорганизуете, чтобы выставить соавторов. Это кодовый запах, если вы проводите рефакторинг и нет соавторов (так что вам не нужно ничего заглушать или насмехаться).

РЕДАКТИРОВАТЬ : То, что автор подразумевает под "сотрудниками" является зависимости Некоторые из его примеров для зависимостей - это классы, которые обращаются к базе данных или к файловой системе ОС. Здесь он определяет заглушку и начинает использовать слово «соавтор»:

Заглушка является управляемой для замены существующей зависимости (или сотрудника ) в системе.

У автора нет примера такого запаха кода, и мне трудно понять, как это выглядит. Может кто-нибудь объяснить это немного больше и, возможно, привести конкретный пример?

программист
источник
Я думаю, что путаница здесь проистекает из слова «сотрудники». Должен признать, я не уверен, что он имеет в виду в этом контексте.
Россипедия
@ Брайан Росс, я обновил пост тем, как автор использует слово «соавтор». Спасибо!
программист

Ответы:

3

Я думаю, что это то, к чему стремится автор.

В моем примере кода у меня есть временное окно, которое принимает выходную величину плюс время запуска и остановки. Намерение состоит в том, чтобы нарисовать выходное окно в течение 24 часов. Складка добавляется, когда время начала больше, чем время остановки, потому что это временное окно, которое охватывает полночь.

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

Разоблачение double outputбудет запахом кода, поскольку это не коллаборатор - это элемент, явно скрытый самим классом, который имеет условную логику GetOutputдля определения того, что должно быть возвращено.

Копание в bools / timespans сделало бы модульные тесты более всесторонними. Он говорит, что это хорошо.
Копание в двойник outputпотребовало бы дополнительной логики в вашем модульном тесте, который отражал бы то, что GetOutputделал. Это будет запах кода, на который он ссылается.

открытый класс TimeWindow
{
  приватный бул isConst;
  приватные промежутки времени до середины ночи;
  частный интервал времени start1;
  приватный TimeSpan stop1;
  частный интервал времени start2;
  приватный TimeSpan stop2;
  частный двойной выход;

  общедоступное TimeWindow (удвоение, запуск TimeSpan, остановка TimeSpan)
  {
    выход = выход;

    если (начало == остановка)
      isConst = true;
    иначе если (начало> остановка)
    {
      spansMidnight = true;
      начало1 = полночь;
      stop1 = стоп;
      start2 = начало;
      стоп2 = полночь;
    }
    еще 
    {
      start1 = начало;
      stop1 = стоп;
    }
  }

  public double GetOutput (время TimeSpan)
  {
    // некоторая логика здесь о том, что / как вернуть
    ...
    обратный вывод;
  }

}

источник
0

Допустим, у нас есть класс домена, и этот класс домена имеет непосредственное знание о уровне персистентности с использованием репозитория, который он использует для предоставления метода «Сохранить» уровня экземпляра, который объекты, работающие в классе домена, могут вызывать для сохранения изменений. сделано без необходимости знания механизма (будь то «хороший» дизайн - это обсуждение другого дня). Рефакторинг класса для предоставления этого репозитория в качестве аргумента свойства и / или конструктора, что позволяет передавать макетированный репозиторий, который может гарантировать, что сделан правильный вызов, как правило, полезен не только для тестирования, но и для общего сопровождения.

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

Keiths
источник