Зачем мне действительно использовать тестирование на основе свойств, если я уже практикую тестирование на основе примеров?
Одно предостережение, которое некоторые разработчики утверждают о TDD с помощью тестов на основе примеров, - это возможное отсутствие каждой действительной обработки ввода.
Давайте рассмотрим простой пример, в котором эти разработчики могут поспорить:
Сделайте программу, которая добавит два числа.
Боб, разработчик начинает писать первый тест:
Учитывая 1 + 3, то результат 4.
Реализация: def add (x: Int, y: Int) = 4
Хорошо, это проходит.
Теперь второй тест:
Учитывая 2 + 2, то результат 4. Реализация все та же: def add (x: Int, y: Int) = 4
Поэтому другие разработчики приходили и говорили ему:
"Теперь вы видите Боба, что тестирование на примере недостаточно с вашими плохими 2 примерами!
Вы не проверяли каждый вывод и смотрели на вашу фактическую реализацию, она потерпит неудачу для других входных данных, результат которых отличается от 4!
Теперь послушайте нас и начните писать некоторые тесты на основе свойств, чтобы охватить все допустимые входные данные.
Итак, давайте начнем с теста коммутативности, ассоциативности и т. Д., Характерных для добавления: свойства добавления!"
Но, но, но... Практика TDD Боба действительно плоха!
Действительно, он хотел применить триангуляцию, но он написал тест, который уже прошел успешно, поскольку реализацию не нужно было изменять!
Чтобы привести к триангуляции, нужно написать тест, который не проходит. И триангуляция является одним из главных ключей практики TDD.
Это позволяет сделать основной шаг: рефакторинг, так как вы должны управлять двумя путями, которые приводят к 2 отличным результатам!
=> Пока тесты становятся конкретными, код становится более универсальным благодаря рефакторингу.
Итак, мой вопрос:
Если мы применяем строгий TDD с хорошей практикой триангуляции, какова реальная выгода от использования основанного на свойствах тестирования, утверждая, что инварианты, которые в 99% случаев уже покрыты хорошим TDD?
Действительно, предположим, что разработчики имеют хороший IQ и реализуют сборку, что имеет смысл;)
Мой пример взят из этих слайдов.
2 ответа
Тестирование на основе свойств очень полезно в тех случаях, когда трудно найти крайние случаи или их так много, что программист может легко пропустить один. Я использовал это, например, когда я реализовывал алгоритм Хиршберга. Нет очевидного способа разделить алгоритм на более мелкие, тривиальные, легко проверяемые TDD части. и трудно вручную создать вход, который охватывает все возможные пути алгоритма. лучший способ - генерировать большое количество различных входных данных, чтобы охватить все пути. и когда автоматическая проверка обнаружит ошибку, добавьте этот конкретный вход в ваши регрессионные тесты
Если вы практикуете TDD, вы знаете, что это способ думать и заниматься дизайном, а не заниматься тестированием.
TDD возникла как инкрементное, в основном, модульное тестирование на основе состояния. Затем TDD в стиле взаимодействия (то есть в стиле mockist или в стиле Лондона) изменил наше представление о коде разработки кода.
TDD, основанный на свойствах, также имеет возможность изменить способ разработки кода. Вместо того, чтобы генерировать примеры для продвижения нашего дизайна, мы используем свойства. Это приводит к меньшему количеству тестов, которые более удобны в обслуживании с лучшим охватом тестов.
С другой стороны, это сложнее и требует больше обдумывания, чем TDD на основе примеров.