Инициализировать объект для тестирования в SetUp или во время метода тестирования? - PullRequest
5 голосов
/ 19 ноября 2008

Мне было интересно, должен ли объект для проверки быть полем и таким образом настраиваться во время метода SetUp (т. Е. JUnit, nUnit, MS Test, ...).

Рассмотрим следующие примеры (это C♯ с MsTest, но идея должна быть аналогичной для любого другого языка и среды тестирования):

public class SomeStuff
{
    public string Value { get; private set; }

    public SomeStuff(string value)
    {
        this.Value = value;
    }
}


[TestClass]
public class SomeStuffTestWithSetUp
{
    private string value;
    private SomeStuff someStuff;

    [TestInitialize]
    public void MyTestInitialize()
    {
        this.value = Guid.NewGuid().ToString();
        this.someStuff = new SomeStuff(this.value);
    }

    [TestCleanup]
    public void MyTestCleanup()
    {
        this.someStuff = null;
        this.value = string.Empty;
    }

    [TestMethod]
    public void TestGetValue()
    {
        Assert.AreEqual(this.value, this.someStuff.Value);
    }
}

[TestClass]
public class SomeStuffTestWithoutSetup
{
    [TestMethod]
    public void TestGetValue()
    {
        string value = Guid.NewGuid().ToString();
        SomeStuff someStuff = new SomeStuff(value);
        Assert.AreEqual(value, someStuff.Value);
    }
}

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

Каковы плюсы и минусы каждого подхода? Есть ли «Лучшие практики»?

Ответы [ 6 ]

8 голосов
/ 19 ноября 2008

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

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

Намного легче читать, когда вы видите тестовый вывод, который делает это:

OrderFulfillmentServiceTests.cs

  • with_an_order_from_a_new_customer

    • следует проверить их кредит в кредитной службе
    • скидка не должна дать
  • с действующим кредитным чеком

    • Это должно уменьшить инвентарь
    • он должен грузить товары
  • с клиентом в Техасе или Калифорнии

    • следует добавить соответствующий налог с продаж
  • при заказе от золотого клиента

    • НЕ ДОЛЖЕН проверять кредит
    • ускоренная доставка должна быть добавлена ​​бесплатно

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

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

Из разговоров с Кентом Беком о дизайне jUnit я знаю, что тестовые классы были способом совместного использования настроек между тестами, поэтому целью было использование общей инициализации. Однако наряду с этим это означает разделение тестов, требующих различной настройки, на отдельные тестовые классы с раскрывающимися именами.

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

Второй подход гораздо более читабелен и намного легче визуально отследить.

Однако первый подход означает меньшее количество повторений.

Я обнаружил, что я склонен использовать SetUp для создания объектов (особенно для вещей с рядом зависимостей), а затем устанавливать значения, используемые в самом тесте. Исходя из опыта, это обеспечивает правильное количество повторного использования кода в сравнении с удобочитаемостью / отслеживаемостью.

0 голосов
/ 26 августа 2015

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

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

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

Подход, который я использую, находится где-то посередине - я использую TearDown и SetUp, чтобы создать тестовую директорию «песочницы» (и удалить ее, когда это будет сделано), а также инициализировать некоторые переменные члена теста с некоторыми значениями по умолчанию, которые будут используется для проверки классов. Затем я настраиваю некоторые «вспомогательные методы» - один из них обычно называется InstantiateClass (). Я использую его для вызова параметров по умолчанию (если есть), которые я могу переопределять по мере необходимости в каждом явном тесте.

[Test]
public void TestSomething()
{
    _myVar = "value";
    InstantiateClass();
    RunTheClass();
    Assert.IsTrue(this, that);
}
0 голосов
/ 19 ноября 2008

Лично я использую методы Setup и Teardown по двум различным причинам, хотя я предполагаю, что другие будут иметь разные причины.

  1. Используйте методы Setup и Teardown, когда существует общая логика инициирования, которая используется всеми тестами, и один экземпляр объекта (объектов), созданный в программе установки, предназначен для повторного использования.
  2. Используйте методы Setup и Teardown, когда время, необходимое для создания и уничтожения любого созданного объекта (объектов), занимает достаточно времени, чтобы замедлить процесс модульного тестирования при повторении в каждом TestMethod.

Чтобы дать вам представление о том, как часто я выполняю эти сценарии, в проекте, над которым я сейчас работаю, только два из моих тестовых классов (из примерно восьмидесяти) явно нуждаются в методах Setup и Teardown, оба раз это должно было удовлетворить мою вторую причину из-за 10-секундного максимума, который я включил для каждого выполнения теста.

Я также предпочитаю удобочитаемость создания и уничтожения объекта (-ов) внутри TestMethod, хотя для меня это не точка взлома или продажи.

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