В какой степени вы тестируете функциональность? - PullRequest
1 голос
/ 11 ноября 2010

У меня вопрос по модульному тестированию.Я обрисую это на примере.

Скажем, я пишу приложение командной строки, которое имеет множество приемлемых команд, и у каждой команды есть свои приемлемые аргументы.Например: myapp create -DprojectName = newProject -DprojectVersion = 1.0.

Если у меня есть класс с именем Command, который имеет метод validateArguments, который берет список допустимых имен аргументов и сравнивает его со спискомаргументы, которые были указаны пользователем, как бы вы пошли о модульном тестировании этого?

Возможности, которые я вижу:

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

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

    @ Test public void validateArgments_ProjectNameArgPassed_NoExcepton thrown {...}

    @ Проверка открытого void validateArguments_ProjectVersionArgPassed_NoException thrown {...}

и т. Д.

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

Ответы [ 4 ]

5 голосов
/ 11 ноября 2010

Трудно предложить, не зная логику базового кода (есть причина, по которой модульные тесты - это тесты белого ящика, а не черного ящика), но мой подход к этому коду был бы набором модульных тестов, которые содержат тесты в соответствии :

  • Все параметры недействительны
  • Все параметры действительны
  • Различные комбинации допустимых и недопустимых параметров (для проверки не проверенных путей кода из приведенного выше)
  • Различные типы недопустимых параметров, например, не указан, неправильный формат (-projectVersion = Бегемот), неправильные значения (-projectVersion = 99.0) и т. д.
  • Любые другие неисправности, о которых я мог подумать.

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

2 голосов
/ 12 ноября 2010

Это немного зависит от того, какую среду тестирования и язык вы используете.Большинство из них (по крайней мере, в C #) позволяют писать так называемые управляемые данными тесты .Это позволяет вам указать метод тестирования аргументами, которые вы хотите проверить, и в то же время указать ожидаемый результат.

Например, такой тест с Gallio будет выглядеть следующим образом:

[Row("prj1", "1.0", true)]
[Row("blah", "Hippopotamus", false)]
[Row(null, "1.0", false, ExpectedException = typeof(NullReferenceException))]
public void TestArguments(string arg1, string arg2, bool expectedResult)
{
    var result = myApp.ValidateArguments(args);

    Assert.AreEqual(expectedResult, result);
}

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

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

HTH.Томас

1 голос
/ 12 ноября 2010

Я склонен разбивать его по важности кода.

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

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

Внизу находится код с низким уровнем воздействия - код форматирования / отображения;прямое сравнение значений и т. д., где стоимость обслуживания этих тестов перевешивает преимущества 100% правильного кода.

1 голос
/ 12 ноября 2010

Согласитесь с dlanod, объем тестирования UNIT должен ограничиваться тестированием наименьшего компилируемого компонента системы.Ваш подход к тестированию больше похож на тестирование в greybox, но не говорит, что это неправильный подход.Опять же, трудно определить, какой метод следует использовать, зависит от размера и сложности кода / класса.

Другая важная задача тестирования UNIT - определить уровень покрытия кода, а не функциональное покрытие.В действительности менее 50% кода обслуживает 90% сценариев сценариев использования.Если ваше приложение небольшого размера, используйте подход «серого квадрата», в котором вы можете использовать сетку UNIT и функциональное тестирование, в противном случае рекомендуется разделить их.Надеюсь это поможет.

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