Как генерировать случайные элементы в зависимости от предыдущих элементов с помощью Quickcheck?

Я использую QuickCheck для генеративного тестирования в Clojure.

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

  • сгенерировать первое простое число из списка простых чисел (пока все хорошо)
  • сгенерировать второе простое число, которое меньше первого
  • сгенерировать третье простое число, которое меньше первого

Однако я понятия не имею, как это сделать с помощью QuickCheck.

Вот еще более простой, глупый пример, который не работает:

(prop/for-all [a (gen/choose 1 10)
               b (gen/such-that #(= a %) (gen/choose 1 10))]
                (= a b))

Это не работает, потому что a не может быть разрешен (prop/for-all не похож на оператор let).

Итак, как я могу сгенерировать три простых числа при условии, что два последних меньше первого?


person Cedric Martin    schedule 27.06.2014    source источник


Ответы (1)


В test.check мы можем использовать gen/bind в качестве оператора связывания в монаде генератора, поэтому мы можем использовать его для создания генераторов, которые зависят от других генераторов.

Например, чтобы сгенерировать пары [a b], где у нас должно быть (>= a b), мы можем использовать этот генератор:

(def pair-gen (gen/bind (gen/choose 1 10)
                        (fn [a]
                          (gen/bind (gen/choose 1 a)
                                    (fn [b]
                                      (gen/return [a b]))))))

Чтобы удовлетворить себя:

(c/quick-check 10000
               (prop/for-all [[a b] pair-gen]
                 (>= a b)))

gen/bind принимает генератор g и функцию f. Он генерирует значение из g, назовем его x. Затем gen/bind возвращает значение (f x), которое должно быть новым генератором. gen/return — это генератор, который генерирует только свой аргумент (поэтому выше я использовал его для возврата пар).

person mange    schedule 27.06.2014