Спецификация Clojure — переопределить генератор проверки для предиката

#clojure #clojure.spec #test.check

#clojure #clojure.spec #test.check

Вопрос:

Есть ли способ переопределить генератор для основной функции предиката при вызове clojure.spec.test.alpha/check ?

Можно переопределить генератор предикатов по пути внутри s/gen :

 (gen/generate
 (s/gen
  (s/cat :s string?)
  {[:s] #(gen/return "xyz")}))
  

Но эта опция не существует для test/check :

 (defn xyz [s] s)

(s/fdef xyz
  :args (s/cat :s string?)
  :ret  string?)

;; throws
(test/check
 `xyz
 {:gen {[:args :s] #(gen/return "xyz")}})
  

Имя или символ должны быть указаны, но как называется для string? спецификации? Я пробовал использовать символы, оба ‘string? и `строка? но это тоже не сработало.

Переопределение генератора путем обертывания string? с s/with-gen помощью inside s/fdef приводит к отображению кода генератора внутри документов функции… это влияет на удобочитаемость imo.

Определение новой спецификации ::string только для этой цели кажется неправильным.

Ответ №1:

 (ns so.spec
    (:require [clojure.spec.gen.alpha :as gen]
              [clojure.spec.alpha :as s]
              [clojure.spec.test.alpha :as st]))

(defn xyz [s]
    ; only to make sure it gets called
    (prn s)
    s)

(s/def ::xyz-arguments (s/cat :s string?))

(s/fdef xyz
        :args ::xyz-arguments
        :ret string?)

(st/check
    'so.spec/xyz
    {:gen {::xyz-arguments #(gen/return '("xyz"))}})
  

Комментарии:

1. Да, как я отметил в своем вопросе, вы также могли бы сделать (s/def ::string string?) , а затем использовать (s/cat :s ::string) внутри s/fdef и ::string при переопределении… но я надеялся на более простое решение.

2. Извините, я не прочитал последнюю часть. Я предполагаю, что нет, если только не существует какого-то хитрого способа создать спецификацию с помощью генератора аргументов. [:args :s] не сработает, потому что это должен быть символ или ключевое слово.