Использование библиотеки генеративных тестов в clojure против создания вашей собственной с использованием функций более высокого порядка

Clojure имеет ряд библиотек для генеративного тестирования, таких как test.check, test.generative или data.generators.

Можно использовать функции более высокого порядка для создания случайных генераторов данных, которые можно компоновать, таких как:

(defn gen [create-fn content-fn lazy]
  (fn [] (reduce #(create-fn %1 %2) (for [a lazy] (content-fn)))))

(def a (gen str #(rand-nth [\a \b \c]) (range 10)))
(a)

(def b (gen vector #(rand-int 10) (range 2)))
(b)

(def c (gen hash-set b (range (rand-int 10))))
(c)

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

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

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

1 ответ

Решение

test.check делает это лучше. В частности, предположим, что вы генерируете случайный список из 100 элементов, и ваш тест не пройден: что-то в том, как вы обработали этот список, неверно. Что теперь? Как вы находите основную ошибку? Это, конечно, не зависит именно от этих 100 входов; вы могли бы воспроизвести его со списком из нескольких элементов или даже с пустым списком, если что-то не так с вашим базовым случаем.

Особенность, которая делает все это на самом деле полезным, - это не случайные генераторы, а "сокращение" этих генераторов. Как только test.check находит ввод, который нарушает ваши тесты, он пытается максимально упростить ввод, в то же время прерывая ваши тесты. Для списка целых чисел сокращения достаточно просты, вы можете сделать их самостоятельно: удалить любой элемент или уменьшить любой элемент. Даже это не может быть правдой: выбор порядка выполнения, вероятно, является более сложной проблемой, чем я понимаю. А для больших входных данных, таких как список карт от векторов к трем кортежам [string, int, keyword], вы найдете его полностью неуправляемым, в то время как test.check уже выполнил всю тяжелую работу.

Другие вопросы по тегам