Skip to content

Instantly share code, notes, and snippets.

@dchelimsky
Created August 30, 2019 21:18
Show Gist options
  • Save dchelimsky/7a76662b2779376ecb179aa7be1b75db to your computer and use it in GitHub Desktop.
Save dchelimsky/7a76662b2779376ecb179aa7be1b75db to your computer and use it in GitHub Desktop.
exercise specs
(ns exercise-specs
(:require [clojure.test :as t :refer [deftest is]]
[clojure.string :as str]
[clojure.spec.alpha :as s]
[clojure.tools.namespace.find :as namespace.find]
[clojure.tools.namespace.parse :as namespace.parse]
[clojure.java.io :as io])
(:import (java.io PushbackReader)))
(def ^:dynamic *num-tests* 10)
(def ^:dynamic *report-keys* false)
(defn find-namespaces-with-specs
"Discovers all namespaces under dir (default src) which require
clojure.spec.alpha."
([]
(find-namespaces-with-specs "src"))
([dir]
(->> (namespace.find/find-clojure-sources-in-dir (io/file dir))
(map io/reader)
(map #(PushbackReader. %))
(map namespace.parse/read-ns-decl)
(map (fn [nsd] {:ns (second nsd)
:deps (namespace.parse/deps-from-ns-decl nsd)}))
(filter #(contains? (:deps %) 'clojure.spec.alpha))
(map :ns))))
(defn require-namespaces-with-specs
"Discovers and requires all namespaces under src which depend on clojure.spec.alpha."
([]
(require-namespaces-with-specs "src"))
([dir]
(let [nses (find-namespaces-with-specs dir)]
(dorun (map require nses))
(mapv identity nses))))
(defn find-specs
"Applies xform (transducer) to all the keys in the spec registry. By default, this
returns keyword keys whose namespaces do not begin with 'clojure'."
([]
(find-specs (comp (filter keyword?)
(remove #(str/starts-with? (namespace %) "clojure")))))
([xform]
(->> (keys (s/registry))
(into [] xform)
sort)))
(defn exercise-specs
"Exercises all currently loaded specs, or just those listed in ks
(if they are loaded). For brute force (common case), do this:
(require-namespaces-with-specs)
(exercise-specs)
For something more granular, use find-specs with a filter, e.g.
(require 'some.namespace)
(exercise-specs (find-specs #(comp #{\"some.namespace\"} namespace))) "
([] (exercise-specs (find-specs)))
([ks]
(doseq [k ks]
(when *report-keys* (println k))
(is (nil? (dorun (s/exercise k *num-tests*)))
(str "Error exercising " k)))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment