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

StackOverflow https://stackoverflow.com/questions/97114

Вопрос

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

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

Спасибо.

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

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 #.Однако теперь мы добавили вызов динамической отправки, где было бы достаточно статического, объект больше даже в рабочей версии, и мы добавили новый путь к сбою для конструктора Foo (выделение может завершиться ошибкой).

Неужели я здесь ни о чем не беспокоюсь?Спасибо за отзыв на данный момент!

Это было полезно?

Решение

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

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

Другие советы

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

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

Плохо, очень плохо.

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

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

if (globals.isTest)

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top