Статьи

Атрибут теста № 10 — Изоляция

детская-сумо-suits_zps591b5541 Это последняя, ​​последняя и десятая запись в десяти заповедях атрибутов теста, которые начались здесь . И вы должны прочитать их все.

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

Это изоляция кода . Но тестовая изоляция другая.

Изолированный тест может выполняться отдельно, в комплекте, в любом порядке, независимо от других тестов, и давать согласованные результаты. Мы уже определили в пространстве различные зависимости окружения, которые могут повлиять на результат, и, конечно, протестированный код как-то связан с ним.

Другие тесты также могут создавать зависимость, напрямую или нет. На самом деле, иногда мы можем полагаться на порядок тестов.

Чтобы привести пример, я вызываю свидетеля обвинения: Синглтона.

Вот некоторый основной код, использующий одиночный код:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
public class Counter
{
    private static Counter instance;
    private int count = 0;
    public static void Init()
    {
        instance = new Counter();
    }
 
    public static Counter GetInstance()
    {
        return instance;
    }
 
    public int GetValue()
    {
        return count++;
    }
}

Довольно просто: статический экземпляр инициализируется при вызове Init. Мы можем написать эти тесты:

01
02
03
04
05
06
07
08
09
10
11
12
[TestMethod]public void CounterInitialized_WorksInIsolation()
{
    Counter.Init();
    var result = Counter.GetInstance().GetValue();
    Assert.AreEqual(0, result);
}
 
[TestMethod]public void CounterNotInitialized_ThrowsInIsolation()
{
    var result = Counter.GetInstance().GetValue();
    Assert.AreEqual(1, result);
}

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

Кстати, мы не просто полагаемся на порядок тестов — мы полагаемся на то, как их запускает тестирующий. Это может быть в том порядке, в котором мы их написали, но не обязательно.

Хотя синглтоны в основном появляются в тестируемом коде, зависимость от тестов может возникать из-за самих тестов Пока вы сохраняете состояние в тестовом классе, включая ложные операции, есть вероятность, что вы зависите от порядка выполнения.

Вы знаете этот трюк?

1
2
public class MyTests: BaseTest {
    ///...

Почему бы не поместить весь общий код в базовый класс, а затем извлечь из него тестовый класс?

Что ж, кроме проблем с читабельностью и мучительной отладки, теперь у нас есть все виды настройки и поведения тестов, которые находятся в другом общем месте. Может случиться так, что сам тест не испытывает помех от других тестов, но мы вводим этот риск, помещая общий код в базовый класс. Кроме того, вам не нужно больше о порядке инициализации. А что, если базовый класс использует синглтон? Выходки наступают.

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

Во избежание проблем с изоляцией:

  • Проверьте код. Если вы можете определить такие схемы использования, как сингелтон, помните об этом и используйте его: либо инициализируйте синглтон перед всем прогоном, либо перезапускайте его перед каждым тестом.
  • Перестановка. Если есть дополнительные зависимости (например, увеличение счетчика), начните думать о перестановке тестов. Поскольку способ написания кода, вы начинаете тестировать больше, чем просто небольшие операции.
  • Не наследуй. Тестовые базовые классы создают взаимозависимость и вредят изоляции.
  • Дразнящий. Используйте насмешки, чтобы контролировать любую общую зависимость.
  • Убирайся Убедитесь, что тесты убираются за собой. Или вместо каждого запуска.

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

Ссылка: Атрибут теста № 10 — Изоляция от нашего партнера по JCG Гила Зильберфельда в блоге Geek Out of Water .