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

Единичное тестирование метода, который вызывает другой метод

Каков наилучший способ unit test метода, который вызывает несколько методов, например:

modify(string value)
{
    if(value.Length > 5)  replaceit(value);

    else changeit(value);
}

Этот псевдо-код имеет метод изменения, который (в настоящее время) вызывает либо replaceit(), либо changeit(). Я уже писал тесты для replaceit и changeit, поэтому для записи нового теста для модификации будет 99% того же набора кода. Мне нужно проверить это, потому что это может измениться в будущем.

Итак, скопируйте ли существующий тестовый код? Переместить тестовый код на общую функцию? Любые другие идеи? Я не уверен в лучшей практике здесь.

4b9b3361

Ответ 1

Это классический тестовый сценарий на основе тестирования на основе поведения и поведения.

В этом смехотворно простом примере проверка вывода прекрасна. Однако в какой-то момент вы столкнетесь с проверками, когда проверка состояния после выполнения сложна. Вместо этого вы хотите проверить поведение (например, проверить, что changeit вызывается с определенным значением).

В этот момент вы, вероятно, должны заглянуть в фреймовую инфраструктуру объекта, такую ​​как Rhino.Mocks(.Net) или Mockito (Java), и начать писать код на основе интерфейса.

Ответ 2

Если вы уже тестировали replaceit() и changeit() самостоятельно, то единственное, что вы оставили для тестирования, - это условие if. Тест modify() с несколькими значениями, чтобы убедиться, что он вызывает правильную функцию в правильных условиях (эти условия null и Strings длиной 4, 5 и 6 для кода примера, который вы указали).

Ответ 3

У вас есть несколько вариантов. Какой из них лучше всего зависит от деталей, которые не ясны из вашего вопроса.

  • test modify так же, как если бы это был несвязанный метод. Преимущество: он может в какой-то момент стать одним.
  • просто проверьте, что вы получили правильность if-statement. То есть достаточно просто проверить, что тесты заставляют вас написать нужную вам реализацию (где вызов replaceit и changeit - это просто самая простая реализация, которая может работать. Если вы практикуете TDD, это должно прийти к вам естественным образом. Преимущество: высокий охват тестированием без особого дублирования усилий.
  • Подкласс и метод переопределения (это метод нарушения зависимости из книги "Эффективная работа с устаревшим кодом" ): протестируйте метод на подклассе, который вы вводите исключительно для целей тестирования, который переопределяет replaceit и changeit с помощью (или переменные, указывающие, был ли метод вызван с правильными значениями). Преимущество: возможно, упростит ваши тесты (или нет), иногда даже просто сделайте тестирование возможным.
  • Извлеките новый класс для методов replaceit и changeit, включая интерфейс для этого класса. Stub или Mock этот интерфейс при тестировании modify. Преимущество: может сделать ваш дизайн более надежным и лучше развязанным/многоразовым в целом (или нет).

Ответ 4

Просто проверьте modify.

modify должен возвращать определенные значения при заданных значениях.

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

И если в будущем вы измените modify на использование разных методов (или нет методов), это не будет, а не должно и не повлияет на ваши тесты.

Тем не менее, проверьте replaceit' and changeit`.

Ответ 5

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

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

Ответ 6

В порядке предпочтения

  • modify (test) имеет всего 2 сценария (каждая рука if stmt), поэтому я бы написал 2 теста для изменения формы.
    Если ожидаемый результат замены (значения) легко определить..

.

public TestModifyIfValueLength..()
    {
      string expectedValue = .. ;// literal result of replaceit(value)
      Assert.Equals( expectedValue, modify("asd") );
    }
  1. Если нет, подумайте об использовании заглушки (используйте подкласс и переопределите changeit, replaceit), чтобы убедиться, что был вызван правильный метод.
  2. Если заглушка - это слишком много работы, делайте макет. Извлеките интерфейс и настройте ожидания на changeit, replaceit.

Допущения

  • У вас есть тесты для replaceit (value) и changeit (value), которые всесторонне проверяют (например, все граничные условия) для этих 2 методов.
  • replaceit() и changeit() являются общедоступными методами. Если нет, вы должны рассмотреть возможность написания тестов только для общедоступных методов. Вы должны быть свободны в настройке/выкидывании частных методов без знания тестового кода.

Ответ 7

Ну, нет, ваш тестовый код не будет на 99% одинаковым, потому что вы на самом деле тестируете что-то другое здесь, если только замена, изменение и изменение не возвращают одинаковые значения.

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

Ответ 8

Если вы уже написали тесты для replaceit() и changeit(), тест для модификации просто проверит, что разные результаты возвращаются в зависимости от значения 'value'. Однако вы просто будете переопределять логику метода в тесте, что немного абсурдно.

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

Ответ 9

При тестировании граничных условий, таких как if (value.length > 5), вы должны убедиться, что ваши тестовые данные содержат значения value, длина которых 4, 5 или 6.

Ответ 10

Вы можете создать func из методов и высмеять эти funcs. Или вы можете создавать виртуальные методы и использовать ночные нотки Rhino - частичный макет, вы можете имитировать эти виртуальные методы.

Ответ 11

Вам в основном нужны 2 теста.

1) Переходите в строку типа "Quick Brown Fox Jumps!". (длина больше пяти), убедитесь, что на значение влияет replaceit(...)

2) Передайте строку типа "Foo" (длина меньше пяти) и убедитесь, что на значение влияет changeit(...)

Ваш тест (в псевдокоде) может выглядеть так:

testLongValue() {
    string testValue = "A value longer than 5 chars";
    string expected = "Replaced!";
    string actual = modify(testValue);
    assertEqual(expected, actual);
}

testShortValue() {
    string testValue = "len4";
    string expected = "Changed!";
    string actual = modify(testValue);
    assertEqual(expected, actual);
}

Очевидно, я мог бы дать вам более реалистичный пример, если бы я знал, что должны были делать функции replacit() и changeit(), но это должно дать вам эту идею. Если он изменяет исходное значение, а не возвращает его, вы можете просто использовать testValue в качестве фактического значения после вызова.

Ответ 12

То же, что и Justin Standard, плюс передача null в качестве значения (что, очевидно, не удастся для фрагмента кода, который вы нам даете;)) Основное правило для модульного тестирования - "проверить только то, что характерно для тестируемого метода". И это довольно... необычно иметь метод, который не вызывает другого.