Параметризованные тесты - когда и почему вы их используете?

15

Недавно на работе у нас возникли разногласия в отношении параметризованного тестирования . Обычно мы используем стиль TDD (или, по крайней мере, пытаемся), поэтому я понимаю преимущества этого подхода. Тем не менее, я изо всех сил пытаюсь увидеть усиление параметризованных тестов. Для справки, мы работаем над сервисом и его библиотеками, которые предоставляются через интерфейс RESTful.

До сих пор я видел тесты, которые, по крайней мере, используют JUnit в Eclipse:

  • Недостаток в деталях - когда тест не пройден, очень трудно увидеть параметры, вызвавшие его неудачу
  • Часто сложный в создании
  • Склонность к созданию после того, как код был написан - строго не недостаток как таковой, но люди начинают с параметризованных тестов, когда они запускают кусок кода?

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

neilprosser
источник
1
Проблема не в идее, а в неуклюжей библиотеке. В C # синтаксис гораздо удобнее, когда вы используете, скажем, MbUnit. Да, это хорошая идея. Добавьте свой собственный код, чтобы упростить этот процесс - читать вещи из файлов - все, что работает. Также посмотрите, как MsTest справляется с этим.
Работа
Мы (Квадрат) написали Burst, чтобы решить некоторые из этих проблем Parameterized. Как правило, это добавляет меньше шаблонного и дает четкое представление о том, где тест не удался.
Даниэль Любаров

Ответы:

4

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

Идея состоит в том, что, хотя вы не проводите исчерпывающее тестирование, большинство дефектов приводят к возникновению «области неисправности», а не изолированной точечной неисправности. Подход DOE Phadke рекомендует использовать ортогональные массивы для достаточно точного выбора пространства параметров, чтобы охватить все возможные области разломов.

Отдельные неисправности, вероятно, не будут идентифицированы, но, как правило, они меньше областей неисправностей.

Подход DOE дает вам систематический способ выбора значений параметров для изменения.

Питер К.
источник
Предоставленная ссылка не работает.
Джош Густ
1
@JoshGust Легко исправляется с помощью Google. Спасибо за внимание.
Питер К.
4

Они могут быть полезны для обеспечения того, чтобы ваш код обрабатывал не только счастливый путь, но и крайние случаи. После того, как вы узнаете, что ваш код работает с обычными переменными, параметризуйте тестовый пример и убедитесь, что нули и 0, пустые строки, большие числа, длинные строки, странные символы Юникода и т. Д. Также работают нормально.

Этель Эванс
источник
2

Существует как минимум два варианта параметризованных тестов, по крайней мере, в JUnit 4.8. Это: Parameterized Tests ( @RunWith(Parameterized.class)), для которого требуется источник данных, который генерирует / считывает предварительно определенные конфигурации параметров, и Theories ( @RunWith(Theories.class)), которые, учитывая один или несколько возможных наборов входных данных для каждого типа аргумента, могут выполнять спецификацию данных методов. Это выглядит более-менее так:

  • указать некоторые возможные значения ( @DataPoints) для строковых аргументов (например null, пустая строка, непустая строка, действительно длинная строка)
  • укажите некоторые возможные значения ( @DataPoints) для аргументов класса Animal (например null, Doginstance, Catinstance, Birdinstance)
  • подготовить, @Theoryкоторый принимает Stringпараметр и Animalпараметр. он будет выполняться с каждой возможной комбинацией возможных значений параметров (в данном примере это будет 4x4 = 16 комбинаций, включая ( null, null))
  • если тестируемый метод не может принять какую-либо комбинацию, используйте Assume.assumeThatстатический импорт для фильтрации недопустимых комбинаций (например, когда вы хотите проверить поведение метода для непустых строк, одной из первых строк будет «предположить, что это не ноль»)

Как написано ранее - не имеет смысла тестировать каждую возможную комбинацию каждого метода (он разбивает тестовые наборы, представьте себе тестирование метода с 5 параметрами, каждый из которых имеет только 5 возможных значений: 5 ** 5 -> более 3000 тестовых прогонов !), но для критически важных методов (таких как методы API) я бы рекомендовал это, просто чтобы быть в безопасности ...

Адам Хепнер
источник
1

Общий пример:

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

  • Примените один и тот же сценарий к разным аргументам. У нас есть сценарий , который работает с Animalобъектом и иметь много подклассов , такие как Dog, Cat, Bird. Создайте список доступных животных и протестируйте сценарий на них.

Бетон для веб-сервиса:

  • Из примера строковых аргументов выше. Проверьте, что происходит с разными аргументами одного типа, но с разными значениями.
Виктор Хурдугачи
источник
0

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

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

Cirem
источник
1
Почему параметры не должны использоваться для удобства написания меньшего количества кода? Нет большого достоинства в предоставлении исчерпывающего списка большого (ish) набора тестовых случаев.
Джонатан Юнис
1
Как ваш ответ дает больше информации, чем остальные 5 ответов?
Адам Цукерман
-2

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

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

Уайетт Барнетт
источник
1
Идеально параметризованные тесты должны иметь форму «соответствует ли элемент (n) в фактическом выводе элементу (n) ожидаемому результату» или подобным, и в этом случае тестирование не требуется. Но для чего-то более сложного я бы предпочел увидеть один-два теста с чистой параметризацией со своими собственными контрольными примерами, чем обычные пометки «мой (тестовый) код явно верен». Если бы это было правдой, вы бы вообще не писали тестовые случаи. Очевидно, что со сложностью можно обойти стороной слишком много, и я не спорю, что нет никакой линии, но я думаю, что есть случаи, когда тестирование является хорошей идеей.