Skip to content

Instantly share code, notes, and snippets.

@dustingetz
Last active April 10, 2020 14:41
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dustingetz/f98f1e6ccbfd9b8c912f2fcb03b270dc to your computer and use it in GitHub Desktop.
Save dustingetz/f98f1e6ccbfd9b8c912f2fcb03b270dc to your computer and use it in GitHub Desktop.

I am tired of black box magic test frameworks with long command line incantations and opaque source code that soaks up weeks of attention to understand, so I really want something lightweight like this to become popular. I don't yet know the gap between this and production test functionality, and don't have much attention to spend on this, what are your ideas?

I especially love Brandon Bloom's idea of (defmacro tests [body]) which can erase the tests at compile time depending on build target. Does this mean we can finally co-locate our tests with our functions, like Rich comment blocks?

(ns contrib.test
  (:gen-class)
  (:require
    [clojure.spec.alpha :as s]
    [taoensso.timbre :refer [warn error info]]))


(defmacro check!
  "Checks v (defaults to *1) against spec, throwing on failure. Returns nil."
  ([spec]
   `(check! ~spec *1))
  ([spec v]
   `(s/assert ~spec ~v)))

(def ^:dynamic *tests* (atom {}))

(defmacro tests [& body]
  (if true                                                  ; target :test
    `(swap! *tests* assoc (ns-name *ns*) '~body)))

;(def script-counter (atom 0))
(defn run-tests []
  ;(println ">> " @*tests*)
  (doseq [[ns body] @*tests*]
    ;(let [ns (symbol (str "cognitect.transcriptor.t_" (swap! script-counter inc)))])
    (in-ns ns)
    ;(clojure.core/use 'clojure.core)
    (doseq [form body]
      (try
        (println "=> " form)
        ; What is this classloader gibblygook
        ; https://github.com/cognitect-labs/transcriptor/blob/05e9eb093b21d9a3458e0d946ad9dab76ae1e1c8/transcriptor.clj#L46-L47
        (let [value (eval form)]
          (set! *3 *2) (set! *2 *1) (set! *1 value))
        (catch Exception e
          (error e))))))

(defn -main [ns & args]
  (alter-var-root #'*err* (constantly *out*))
  (taoensso.timbre/set-level! :info)
  (info "Running tests ...")
  ; load all namespaces
  (require (symbol ns))
  (run-tests))

(comment
  ; Example

  (ns user
    (:require [contrib.test]))

  (tests
    (inc 1)
    (check! #{2})

    (inc 1)
    (check! #{3})

    (inc 42)
    (check! (s/and odd? #{43} #{44}))

    )

  (contrib.test/run-tests)
  )
@dustingetz
Copy link
Author

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment