Является ли условная компиляция допустимой стратегией макета / заглушки для модульного тестирования? - PullRequest
4 голосов
/ 19 сентября 2008

В недавнем вопросе о заглушке во многих ответах предлагались интерфейсы или делегаты C # для реализации заглушек, но один ответ предлагал использовать условную компиляцию, сохраняя статическую привязку в рабочем коде. Этот ответ был изменен на -2 во время чтения, поэтому, по крайней мере, 2 человека действительно думали, что это был неправильный ответ. Возможно, причиной было неправильное использование DEBUG, или, возможно, использование фиксированного значения вместо более обширной проверки. Но я не могу не задаться вопросом:

Является ли использование условной компиляции неподходящим методом для реализации заглушек модульных тестов? Иногда? Всегда

Спасибо.

Edit-add: Я хотел бы добавить пример в качестве эксперимента:

class Foo {
    public Foo() { .. }
    private DateTime Now { 
      get {
#if UNITTEST_Foo
        return Stub_DateTime.Now;
#else
        return DateTime.Now;
#endif
      }
    }
    // .. rest of Foo members
}

по сравнению с

interface IDateTimeStrategy { 
    DateTime Now { get; }
}
class ProductionDateTimeStrategy : IDateTimeStrategy {
  public DateTime Now { get { return DateTime.Now; } }
}
class Foo {
    public Foo() : Foo(new ProductionDateTimeStrategy()) {}
    public Foo(IDateTimeStrategy s) { datetimeStrategy = s; .. }
    private IDateTime_Strategy datetimeStrategy;
    private DateTime Now { get { return datetimeStrategy.Now; } }
}

Что позволяет использовать исходящую зависимость от DateTime.Now через интерфейс C #. Однако теперь мы добавили динамический диспетчерский вызов, в котором было бы достаточно static, объект был бы больше даже в рабочей версии, и мы добавили новый путь отказа для конструктора Foo (распределение может завершиться с ошибкой).

Я здесь ни о чем не беспокоюсь? Спасибо за отзыв!

Ответы [ 6 ]

3 голосов
/ 19 сентября 2008

Старайтесь хранить производственный код отдельно от тестового кода. Поддерживать разные иерархии папок .. разные решения / проекты.

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

2 голосов
/ 19 сентября 2008

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

1 голос
/ 19 сентября 2008

Я подумал о другой причине, это было ужасно:

Много раз, когда вы что-то высмеиваете / заглушки, вы хотите, чтобы его методы возвращали разные результаты в зависимости от того, что вы тестируете. Это либо исключает это, либо делает его неловким, черт возьми.

1 голос
/ 19 сентября 2008

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

Это почти та же причина, по которой вы не должны писать

if (globals.isTest)
1 голос
/ 19 сентября 2008

Нет, это ужасно. Он пропускает тест в ваш производственный код (даже если он выключен)

Плохо плохо.

0 голосов
/ 19 сентября 2008

Это может быть полезно в качестве инструмента для рефакторинга тестируемости в большой кодовой базе. Я вижу, как вы можете использовать такие методы, чтобы сделать небольшие изменения и избежать рефакторинга "большого взрыва". Однако я бы беспокоился о том, чтобы слишком сильно полагаться на такую ​​технику, и постарался бы обеспечить, чтобы такие уловки не жили слишком долго в базе кода, иначе вы рискуете сделать код приложения очень сложным и трудным для исполнения.

...