Это плохая практика - иметь более одного утверждения в модульном тестировании?[закрыто]

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

  •  11-09-2019
  •  | 
  •  

Вопрос

Это плохая практика - иметь более одного утверждения в модульном тестировании?Имеет ли это значение?

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

Решение

Иногда у меня есть ровно один assert для каждого тестового примера, но я думаю, что чаще всего у меня есть несколько assert заявления.

Я видел случай, о котором @Arkain умалчивает, когда очень большой фрагмент кода содержит один набор модульных тестов всего с несколькими тестовыми примерами, и все они помечены testCase1, testCase2, и т.д., и каждый тестовый пример содержит сотни утверждений.И что еще лучше, каждое условие обычно зависит от побочных эффектов предыдущего выполнения.Всякий раз, когда сборка завершается неудачей, неизменно в таком модульном тестировании, требуется довольно много времени, чтобы определить, в чем заключалась проблема.

Но другая крайность - это то, что предполагает ваш вопрос:отдельный тестовый пример для каждого возможного условия.В зависимости от того, что вы тестируете, это может иметь смысл, но часто у меня есть несколько asserts для каждого тестового примера.

Например, если вы написали java.lang.Integer, у вас могут быть некоторые случаи , которые выглядят как:

public void testValueOf() {
    assertEquals(1, Integer.valueOf("1").intValue());
    assertEquals(0, Integer.valueOf("0").intValue());
    assertEquals(-1, Integer.valueOf("-1").intValue());
    assertEquals(Integer.MAX_VALUE, Integer.valueOf("2147483647").intValue());
    assertEquals(Integer.MIN_VALUE, Integer.valueOf("-2147483648").intValue());
    ....
}

public void testValueOfRange() {
    assertNumberFormatException("2147483648");
    assertNumberFormatException("-2147483649");
    ...
}

public void testValueOfNotNumbers() {
    assertNumberFormatException("");
    assertNumberFormatException("notanumber");
    ...
}
private void assertNumberFormatException(String numstr) {
    try {
        int number = Integer.valueOf(numstr).intValue();
        fail("Expected NumberFormatException for string \"" + numstr +
             "\" but instead got the number " + number);
    } catch(NumberFormatException e) {
        // expected exception
    }
}

Несколько простых правил, которые я могу придумать навскидку для определения количества утверждений, которые нужно поместить в тестовый пример:

  • У вас не больше одного assert это зависит от побочных эффектов предыдущего выполнения.
  • Группа asserts вместе, которые тестируют одну и ту же функцию / признак или их аспект - нет необходимости в накладных расходах на несколько модульных тестовых случаев, когда в этом нет необходимости.
  • Любое из вышеперечисленных правил должно быть преодолено практичностью и здравым смыслом.Вероятно, вам не нужны тысячи модульных тестовых примеров с одним утверждением в каждом (или даже с несколькими утверждениями), и вам не нужен один тестовый пример с сотнями assert заявления.

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

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

Однако, если вы тестируете несколько функций в одном модульном тестировании, при сбое будет не так ясно, какие функции вызвали проблему.Помните, что модульные тесты - это ваши друзья, поэтому позвольте им помочь вам.Сделайте это легко доступным, чтобы увидеть, что пошло не так, чтобы вы могли пойти и исправить это.

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

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

var result = controller.Action() as ViewResult;

Assert.IsNotNull( result );
Assert.AreEqual( viewName, result.ViewName );

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

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

Рассмотреть:

assert(list.isEmpty());

FetchValues(list);

assert(list.count == expectedItemCount);

AssertValuesMatch(list,expectedValues);

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

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

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

Вставьте все утверждения, которые вы хотите.Серьезно.

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

Я определенно должен использовать только одно утверждение в методе тестирования!Использование многих утверждений может быть признаком того, что вы тестируете более одной вещи.Более того, есть шанс, что кто-нибудь сможет добавить новое утверждение в ваш тест вместо того, чтобы писать другое.И как вы можете понять, как завершились ваши другие утверждения, когда первое потерпело неудачу?

Возможно, вам также показалась интересной эта статья: https://timetocode.wordpress.com/2016/06/01/zen-of-unit-testing/

Это не имеет значения.Единственное, что имеет значение, - это то, что ваши модульные тесты будут охватывать все возможные ошибки.

Это пример "чрезмерного мышления".

"Модульный тест" должен тестировать 1 единицу, поэтому он должен быть как можно меньше и тестировать только 1 определенную вещь.Я бы предложил иметь только 1 assert

НО я думаю, что нормально иметь 2 утверждения, если они не стоят одно за другим.

Плохой пример

public void ValidateRulesEntry_Valid_ValidConditionsFromFile()
{
    string condition = "Target.HasValue";
    string returnMessage;

    bool successFul = CodeParserTryParseCondition(condition, out returnMessage);


    Assert.IsTrue(successFul);
    Assert.IsFalse(string.IsNullOrEmpty(returnMessage));
    Assert.IsTrue(returnMessage == "OK");

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