Permalink
Browse files

Add capability for selectors to be two functions (one checks the ns, …

…one the vars)

This makes it so that a selector such as :only can prevent unnecessary loading
of namespaces that they aren't going to work on. It is a way for a selector
that knows which namespaces it will touch by the selector's arguments and the
namespace names themselves to not have to load all namespaces.

This commit also fixes a bug introduced by a recent pull request where
'namespaces' could not be resolved. Per discussion with technomancy, provided a
default test selector *always*.
  • Loading branch information...
1 parent e5ca554 commit ba9e56f259b280ad21d91ae0f7c52384d00ab2f8 @Raynes Raynes committed Dec 7, 2012
Showing with 62 additions and 43 deletions.
  1. +2 −1 leiningen-core/src/leiningen/core/project.clj
  2. +60 −42 src/leiningen/test.clj
@@ -91,7 +91,8 @@
:jar-exclusions [#"^\."]
:jvm-opts ["-XX:+TieredCompilation"]
:certificates ["clojars.pem"]
- :uberjar-exclusions [#"(?i)^META-INF/[^/]*\.(SF|RSA|DSA)$"]})
+ :uberjar-exclusions [#"(?i)^META-INF/[^/]*\.(SF|RSA|DSA)$"]
+ :test-selectors {:default '(constantly true)}})
(defn- dep-key
"The unique key used to dedupe dependencies."
View
@@ -16,52 +16,63 @@
(resolve 'clojure.test/test-var)
(fn test-var-with-selector [test-var# var#]
(when (reduce (fn [acc# [selector# args#]]
- (or acc#
- (apply selector#
- (merge (-> var# meta :ns meta)
- (assoc (meta var#) ::var var#))
- args#)))
+ (let [sfn# (if (vector? selector#)
+ (second selector#)
+ selector#)]
+ (or acc#
+ (apply sfn#
+ (merge (-> var# meta :ns meta)
+ (assoc (meta var#) ::var var#))
+ args#))))
false ~selectors)
(test-var# var#))))))
+(defn- form-for-select-namespaces [namespaces selectors]
+ `(reduce (fn [acc# [f# args#]]
+ (if (vector? f#)
+ (filter #(apply (first f#) % args#) acc#)
+ acc#))
+ '~namespaces ~selectors))
+
(defn form-for-testing-namespaces
"Return a form that when eval'd in the context of the project will test
each namespace and print an overall summary."
([namespaces _ & [selectors]]
- `(do
- (when (seq '~namespaces)
- (apply require :reload '~namespaces))
- ~(form-for-hook-selectors selectors)
- (let [failures# (atom #{})
- selected-namespaces# ~(if (seq selectors)
- `(distinct
- (for [ns# '~namespaces
- [_# var#] (ns-publics ns#)
- :when (reduce (fn [acc# [selector# args#]]
- (or acc#
- (apply selector#
- (merge (-> var# meta :ns meta)
- (assoc (meta var#) ::var var#))
- args#)))
- false ~selectors)]
- ns#))
- 'namespaces)
- _# (leiningen.core.injected/add-hook
- #'clojure.test/report
- (fn [report# m# & args#]
- (when (#{:error :fail} (:type m#))
- (swap! failures# conj
- (-> clojure.test/*testing-vars*
- first meta :ns ns-name)))
- (if (= :begin-test-ns (:type m#))
- (clojure.test/with-test-out
- (println "\nlein test" (ns-name (:ns m#))))
- (apply report# m# args#))))
- summary# (binding [clojure.test/*test-out* *out*]
- (apply ~'clojure.test/run-tests selected-namespaces#))]
- (spit ".lein-failures" (pr-str @failures#))
- (when ~*exit-after-tests*
- (System/exit (+ (:error summary#) (:fail summary#))))))))
+ (let [ns-sym (gensym "namespaces")]
+ `(let [~ns-sym ~(form-for-select-namespaces namespaces selectors)]
+ (when (seq ~ns-sym)
+ (apply require :reload ~ns-sym))
+ ~(form-for-hook-selectors selectors)
+ (let [failures# (atom #{})
+ selected-namespaces# (distinct
+ (for [ns# ~ns-sym
+ [_# var#] (ns-publics ns#)
+ :when (reduce (fn [acc# [selector# args#]]
+ (or acc#
+ (apply (if (vector? selector#)
+ (second selector#)
+ selector#)
+ (merge (-> var# meta :ns meta)
+ (assoc (meta var#) ::var var#))
+ args#)))
+ false ~selectors)]
+ ns#))
+ _# (leiningen.core.injected/add-hook
+ #'clojure.test/report
+ (fn [report# m# & args#]
+ (when (#{:error :fail} (:type m#))
+ (swap! failures# conj
+ (-> clojure.test/*testing-vars*
+ first meta :ns ns-name)))
+ (if (= :begin-test-ns (:type m#))
+ (clojure.test/with-test-out
+ (println "\nlein test" (ns-name (:ns m#))))
+ (apply report# m# args#))))
+ summary# (binding [clojure.test/*test-out* *out*]
+ (apply ~'clojure.test/run-tests selected-namespaces#))]
+ (spit ".lein-failures" (pr-str @failures#))
+ (when ~*exit-after-tests*
+ (System/exit (+ (:error summary#) (:fail summary#)))))))))
(defn- split-selectors [args]
(let [[nses selectors] (split-with (complement keyword?) args)]
@@ -82,8 +93,15 @@
[selector-form v]))
(def ^:private only-form
- '(fn [m & vars]
- (some #(= (str "#'" %) (-> m ::var str)) vars)))
+ ['(fn [ns & vars]
+ ((set (for [v vars]
+ (-> (str v)
+ (.split "/")
+ (first)
+ (symbol))))
+ ns))
+ '(fn [m & vars]
+ (some #(= (str "#'" %) (-> m ::var str)) vars))])
(defn- read-args [args project]
(let [args (map read-string args)
@@ -136,4 +154,4 @@ tests are run."
form (form-for-testing-namespaces nses nil (vec selectors))]
(try (eval/eval-in-project project form '(require 'clojure.test))
(catch clojure.lang.ExceptionInfo e
- (main/abort "Tests failed."))))))
+ (main/abort "Tests failed."))))))

0 comments on commit ba9e56f

Please sign in to comment.