Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
.calva/repl.calva-repl
.clj-kondo/.cache
.cpcache
.lsp/.cache
.portal/vs-code.edn
.rebl
.rebl.sh
.idea/
Expand Down
54 changes: 48 additions & 6 deletions src/cognitect/test_runner.clj
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
(ns cognitect.test-runner
(:require [clojure.tools.namespace.find :as find]
(:require [cognitect.test-runner.protocols :as p]
[clojure.tools.namespace.find :as find]
[clojure.java.io :as io]
[clojure.test :as test]
[clojure.test.junit :as junit]
[clojure.test.tap :as tap]
[clojure.tools.cli :as cli])
(:refer-clojure :exclude [test]))

Expand Down Expand Up @@ -53,27 +56,61 @@
(assoc :test (::test %))
(dissoc ::test)))))))

(defn- contains-tests?
(defn- ns-contains-tests?
"Check if a namespace contains some tests to be executed."
[ns]
(some (comp :test meta)
(-> ns ns-publics vals)))

(defrecord ClojureTestRunner []
p/TestRunner
(enable-filtering! [_ options nses]
(filter-vars! nses (var-filter options)))
(contains-tests? [_ _ ns] (ns-contains-tests? ns))
(run-tests [this options nses]
;; we only care about junit and tap (other test runners might care about
;; other values)
(if-let [outputs (seq (filter #{'junit 'tap} (:output options)))]
(doseq [output outputs]
(case output
junit
(junit/with-junit-output
(apply test/run-tests (filter #(p/contains-tests? this options %) nses)))
tap
(tap/with-tap-output
(apply test/run-tests (filter #(p/contains-tests? this options %) nses)))))
(apply test/run-tests (filter #(p/contains-tests? this options %) nses))))
(disable-filtering! [_ _ nses]
(restore-vars! nses)))

(defn create-clojure-test-runner []
(->ClojureTestRunner))

(defn test
[options]
(let [dirs (or (:dir options)
#{"test"})
nses (->> dirs
(map io/file)
(mapcat find/find-namespaces-in-dir))
nses (filter (ns-filter options) nses)]
nses (filter (ns-filter options) nses)
tsym (or (:test-runner-fn options)
'cognitect.test-runner/create-clojure-test-runner)
t-fn (try
(require (symbol (namespace tsym)))
(resolve tsym)
(catch Throwable t
(println "Unable to find test runner function:" tsym)
(throw t)))
;; create the test runner:
trun (t-fn)]
(println (format "\nRunning tests in %s" dirs))
(dorun (map require nses))
(try
(filter-vars! nses (var-filter options))
(apply test/run-tests (filter contains-tests? nses))
(p/enable-filtering! trun options nses)
(p/run-tests trun options nses)
(finally
(restore-vars! nses)))))
(p/disable-filtering! trun options nses)))))

(defn- parse-kw
[^String s]
Expand Down Expand Up @@ -102,6 +139,11 @@
["-e" "--exclude KEYWORD" "Exclude tests with this metadata keyword."
:parse-fn parse-kw
:assoc-fn accumulate]
["-t" "--test-runner-fn SYMBOL" "Symbol indicating the test runner function to use."
:parse-fn symbol]
[nil "--output SYMBOL" "Output format, specific to the selected test runner."
:parse-fn symbol
:assoc-fn (fn [m k v] (update m k (fnil conj []) v))]
["-H" "--test-help" "Display this help message"]])

(defn- help
Expand Down
14 changes: 10 additions & 4 deletions src/cognitect/test_runner/api.clj
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
[cognitect.test-runner :as tr]))

(defn- do-test
[{:keys [dirs nses patterns vars includes excludes]}]
[{:keys [dirs nses patterns vars includes excludes test-runner-fn outputs]}]
(let [adapted {:dir (when (seq dirs) (set dirs))
:namespace (when (seq nses) (set nses))
:namespace-regex (when (seq patterns) (map re-pattern patterns))
:var (when (seq vars) (set vars))
:include (when (seq includes) (set includes))
:exclude (when (seq excludes) (set excludes))}]
:exclude (when (seq excludes) (set excludes))
:test-runner-fn test-runner-fn
:output (when (seq outputs) (vec outputs))}]
(tr/test adapted)))

(defn test
Expand All @@ -22,9 +24,13 @@
* :vars - coll of fully qualified symbols to run tests on
* :includes - coll of test metadata keywords to include
* :excludes - coll of test metadata keywords to exclude
* :test-runner-fn - symbol identifying test runner creation function
* :outputs - coll of output formats (symbols) to use

If neither :nses nor :patterns is supplied, use `:patterns [\".*-test$\"]`."
If neither :nses nor :patterns is supplied, use `:patterns [\".*-test$\"]`.

Not all output formats produce a fail/error summary."
[opts]
(let [{:keys [fail error]} (do-test opts)]
(let [{:keys [fail error] :or {fail 0, error 0}} (do-test opts)]
(when (> (+ fail error) 0)
(throw (ex-info "Test failures or errors occurred." {})))))
7 changes: 7 additions & 0 deletions src/cognitect/test_runner/protocols.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
(ns cognitect.test-runner.protocols)

(defprotocol TestRunner :extend-via-metadata true
(enable-filtering! [this opts nses])
(contains-tests? [this opts ns])
(run-tests [this opts nses])
(disable-filtering! [this opts nses]))