-
Notifications
You must be signed in to change notification settings - Fork 10
/
bat_test.clj
132 lines (114 loc) · 5.09 KB
/
bat_test.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
(ns leiningen.bat-test
(:require [leiningen.help]
[leiningen.core.eval :as eval]
[leiningen.core.project :as project]
[leiningen.core.main :as main]
[leiningen.help :as help]
[leiningen.test :as test]
[clojure.java.io :as io]
[metosin.bat-test.version :refer [+version+]]))
(def profile {:dependencies [['metosin/bat-test +version+]
['eftest "0.5.4"]
['org.clojure/tools.namespace "0.3.0-alpha4"]
['cloverage "1.0.13"]
['watchtower "0.1.1"]]})
(defn quoted-namespace [key s]
(try
`'~(-> s namespace symbol)
(catch NullPointerException cause
(throw (ex-info (format "%s symbol must be namespace qualified" key) {key s} cause)))))
(defn report-namespaces [report]
(cond
(vector? report) (mapcat report-namespaces report)
(map? report) (report-namespaces (:type report))
(symbol? report) [(quoted-namespace :report report)]
:else nil))
(defn used-namespaces [{:keys [report on-start on-end filter]}]
(cond-> (report-namespaces report)
filter (conj (quoted-namespace :filter filter))
on-start (conj (quoted-namespace :on-start on-start))
on-end (conj (quoted-namespace :on-end on-end))))
(defn- run-tests [project opts watch?]
(let [watch-directories (vec (concat (:test-paths project)
(:source-paths project)
(:resource-paths project)))
opts (assoc opts :watch-directories watch-directories)]
(eval/eval-in-project
project
(if watch?
`(do
(System/setProperty "java.awt.headless" "true")
(metosin.bat-test.impl/enter-key-listener ~opts)
@(watchtower.core/watcher
~watch-directories
(watchtower.core/rate 100)
(watchtower.core/file-filter watchtower.core/ignore-dotfiles)
(watchtower.core/file-filter (watchtower.core/extensions :clj :cljc))
(watchtower.core/on-change (fn [~'_]
(println)
(metosin.bat-test.impl/run ~opts)))))
`(let [summary# (metosin.bat-test.impl/run ~opts)
exit-code# (+ (:fail summary# 0) (:error summary# 0))]
(if ~(= :leiningen (:eval-in project))
exit-code#
(System/exit exit-code#))))
`(require 'metosin.bat-test.impl 'watchtower.core
~@(used-namespaces opts)))))
;; For docstrings
(defn- once
"Run tests once"
[project]
nil)
(defn- auto
"Run tests, then watch for changes and re-run until interrupted."
[project]
nil)
(defn bat-test
"Run clojure.test tests.
Changed namespaces are reloaded using clojure.tools.namespace.
Only tests in changed or affected namespaces are run.
Reporter can be either:
- vector List of reporters to run, items can be other allowed values
- map Map with property `:type` which can be one of the following options
and optional `:output-to` property which will redirect the output
to a file.
- keyword Shorthand to use the built-in eftest reporters: :pretty, :progress, :junit
- symbol Symbol pointing to any reporter fn
Default reporter is :progress.
Options should be provided using `:bat-test` key in project map.
Available options:
:test-matcher Regex used to select test namespaces
:parallel? Run tests parallel (default off)
:report Reporting function
:filter Function to filter the test vars
:on-start Function to be called before running tests (after reloading namespaces)
:on-end Function to be called after running tests
:cloverage-opts Cloverage options
:notify-command String or vector describing a command to run after tests
Also supports Lein test selectors, check `lein test help` for more information.
Arguments:
- once, auto, cloverage, help
- test selectors"
{:help-arglists '([& tests])
:subtasks [#'once #'auto]}
[project & args]
(let [subtask (or (some #{"auto" "once" "help" "cloverage"} args) "once")
args (remove #{"auto" "once" "help" "cloverage"} args)
;; read-args tries to find namespaces in test-paths if args doesn't contain namespaces
[namespaces selectors] (test/read-args args (assoc project :test-paths nil))
project (project/merge-profiles project [:leiningen/test :test profile])
config (assoc (:bat-test project)
:selectors (vec selectors)
:namespaces (mapv (fn [n] `'~n) namespaces)
:cloverage (= "cloverage" subtask))]
(case subtask
("once" "cloverage")
(try
(when-let [n (run-tests project config false)]
(when (and (number? n) (pos? n))
(throw (ex-info "Tests failed." {:exit-code n}))))
(catch clojure.lang.ExceptionInfo e
(main/abort "Tests failed.")))
"auto" (run-tests project config true)
"help" (println (help/help-for "bat-test"))
(main/warn "Unknown task."))))