Вы используете TestInitialize или конструктор класса тестов для подготовки каждого теста? и почему?

Этот вопрос касается модульного тестирования в Visual Studio с использованием MSTest (это важно из-за MSTest порядка выполнения). Оба метода, отмеченные [TestInitialize] и конструктор тестового класса, будут выполняться перед каждым тестовым методом.

Итак, вопрос в том, что вы обычно делаете в каждой из этих областей? Вы избегаете выполнения определенных действий? В чем причина: стиль, технические, суеверия?

Ответ 1

Конструктор - это просто структура, предоставляемая языком. Кажется, что каждая тестовая структура имеет свой собственный управляемый жизненный цикл "initialize". Вероятно, вы столкнулись с трудностями при использовании конструктора, чтобы мутировать ваших локальных жителей.

MSTest: Вы получаете весь новый экземпляр тестового класса для каждого TestMethod. Это может быть единственный случай, когда это нормально, чтобы мутировать ваши локальные жители в конструкторе, инициализаторе или методе тестирования и не влиять на другие методы тестирования.

public class TestsForWhatever
{
    public TestsForWhatever()
    {
        // You get one of these per test method, yay!
    }

    [TestInitialize] 
    public void Initialize() 
    {
        // and one of these too! 
    }

    [TestMethod]
    public void AssertItDoesSomething() { }

    [TestMethod]
    public void AssertItDoesSomethingElse() { }
}

MSpec: Вы получите только Establish и Because для всех своих утверждений (It). Итак, не мутируйте своих локальных жителей в своих утверждениях. И не зависят от мутаций локальных жителей в базовых контекстах (если вы их используете).

[Subject(typeof(Whatever))]
public class When_doing_whatever
{
    Establish context = () => 
    { 
        // one of these for all your Its
    };

    Because of = () => _subject.DoWhatever();

    It should_do_something;
    It should_do_something_else;
}

Ответ 2

Вот некоторые преимущества, которые я нашел с помощью TestInitialize.

  • Некоторые переменные среды (например, TestContext) недоступны до тех пор, пока не будет создан экземпляр тестового класса.
  • Может потребоваться реализация с производным классом, пометив базовый тег метода TestInitialize.
  • Может легко переопределить базовый метод TestInitialize и определить, следует ли вызывать базовый impl до производного impl, после или вообще. Напротив, если вы выберете тестовый класс из базового тестового класса, в случае безпараметрического конструктора, базовый ctor будет вызываться независимо от того, планируете вы это или нет.
  • Его явное определение делает намерения понятными и дополняет метод TestCleanup. Вы можете утверждать, что вы можете создать деструктор для каждого конструктора, но это не гарантирует, что MS Test будет обрабатывать деструкторы, как и следовало ожидать.

Ответ 3

Основным преимуществом использования TestInitialize() или ClassInitialize(), а не экземпляра тестового класса или статических конструкторов является его явный характер. Он четко сообщает, что вы делаете некоторые настройки перед вашими испытаниями. Выполнение этого последовательно должно улучшить ремонтопригодность в долгосрочной перспективе.

Ответ 4

Я предпочитаю использовать метод [TestInitialize] для выполнения экземпляра тестируемого объекта и его параметров. Я выполняю только работу в конструкторе, если необходимо создать экземпляр базового класса тестирования (обычно это я создаю или обновляю репозитории и т.д.). Это помогает мне логически и физически сохранять код схемы тестирования и тестовый код.

Ответ 5

Этот вопрос также задан (позже) в В чем разница между использованием конструктора в VS Testing framework и атрибутом TestInitialize()?

FWIW Я предполагаю, что "конструктор класса" означает конструктор экземпляра (а не статический конструктор).

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

Ответ 6

Тестируемый объект не требует создания экземпляра в методе [TestInitialize]. Вы можете проверить конструктор вашего объекта в методе test [Test].

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

Ответ 7

Я использую конструктор, если вам не нужен TestContext.

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

Ответ 8

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

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

Ответ 9

Я знаю, что опаздываю на вечеринку, но с async есть еще одна причина (которая не исчезла, когда задавался этот вопрос) для [TestInitialize]. Позволяет вам выполнять async операции для установки (например, загружать файл), что невозможно в конструкторе:

        private string approver;        

        [TestInitialize]
        public async Task Initialize()
        {
            approver = File.ReadAllTextAsync("approver.json");
        }