Подтвердить что ты не робот

Неужели плохая практика имеет более одного утверждения в unit test?

Неужели плохая практика имеет более одного утверждения в unit test? Это имеет значение?

4b9b3361

Ответ 1

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

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

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

Например, если вы написали 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, который зависит от побочных эффектов предыдущего исполнения.
  • Группа assert вместе, которые проверяют одну и ту же функцию/функцию или ее фасет - нет необходимости в накладных расходах в нескольких случаях unit test, когда это не необходимо.
  • Любое из приведенных выше правил должно быть переопределено практичностью и здравым смыслом. Вероятно, вам не нужны тысячи unit test случаев с одним утверждением в каждом (или даже несколько утверждений), и вам не нужен один тестовый пример с сотнями операторов assert.

Ответ 2

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

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

Ответ 3

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

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

var result = controller.Action() as ViewResult;

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

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

Ответ 4

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

Рассмотрим:

assert(list.isEmpty());

FetchValues(list);

assert(list.count == expectedItemCount);

AssertValuesMatch(list,expectedValues);

Да, я мог бы разделить два условия сообщения на два теста, но в зависимости от стоимости FetchValues ​​можно было бы без усилий замедлить общий тестовый процесс.

Ответ 5

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

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

Ответ 6

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

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

Ответ 7

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

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

Ответ 8

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

Вы также можете найти интересную статью: https://timetocode.wordpress.com/2016/06/01/zen-of-unit-testing/

Ответ 9

A "Unit test" должен протестировать 1 блок, поэтому будьте как можно меньше и проверьте только одну вещь. Я предлагаю иметь только 1 утверждение

НО Я думаю, что его нормально иметь 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");

}