Skip to content

Instantly share code, notes, and snippets.

@mccraigmccraig
Created November 1, 2018 18:40
Show Gist options
  • Save mccraigmccraig/52ad2b32c7b8a69bb2efb8cebebbb0de to your computer and use it in GitHub Desktop.
Save mccraigmccraig/52ad2b32c7b8a69bb2efb8cebebbb0de to your computer and use it in GitHub Desktop.
(ns prpr.test
#?(:clj (:require
[prpr.util.macro :refer [if-cljs]]
[clojure.test :as t]
[prpr.promise :as prpr])
:cljs (:require
[prpr.util.macro :refer-macros [if-cljs]]
[cljs.test :as t :refer-macros [async]]
[prpr.promise :as prpr])))
;; lord help me
#?(:clj
(defonce test-binding-frame (atom nil)))
#?(:clj
(defmacro record-test-binding-frame
[& body]
;; pass the actual original binding frame around, not a clone,
;; so that any changes on other threads make their way back to the
;; original thread
`(let [orig-frame# (clojure.lang.Var/getThreadBindingFrame)]
(try
(reset! test-binding-frame orig-frame#)
~@body
(finally
(reset! test-binding-frame nil))))))
#?(:clj
(defmacro with-test-binding-frame
[& body]
`(let [curr-frame# (clojure.lang.Var/getThreadBindingFrame)]
(try
(clojure.lang.Var/resetThreadBindingFrame @test-binding-frame)
~@body
(finally
(clojure.lang.Var/resetThreadBindingFrame curr-frame#))))))
;; a bunch of test macros for comparable async testing
;; in clj or cljs... some just reference the underlying clojure.test
;; macros, but are here to make ns :require forms simpler
(comment
(ns some.ns
(:require
#?(:clj [prpr.test :refer [deftest test-async is testing]]
:cljs [prpr.test :refer-macros [deftest test-async is testing]]))))
#?(:clj
(defmacro deftest
[& body]
`(clojure.test/deftest ~@body)))
;; if you make the body of test-async a form or forms that
;; each return a promise... this will complete them
#?(:clj
(defmacro test-async
[& ps]
(if-cljs
`(clojure.test/async done
(prpr/catch-error-log
"test-async"
(prpr/chain-pr
(prpr/all-pr ~@ps)
(fn [_] (done)))))
`(let [body# (fn []
(with-test-binding-frame
(prpr/all-pr ~@ps)))]
(record-test-binding-frame
@(body#))))))
#?(:clj
(defmacro is
[& body]
(if-cljs
`(clojure.test/is ~@body)
`(with-test-binding-frame
(clojure.test/is ~@body)))))
#?(:clj
(defmacro testing
[& body]
(if-cljs
`(clojure.test/testing ~@body)
`(with-test-binding-frame
(clojure.test/testing ~@body)))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment