From 73d55215c64f3fdafe5fe987a5a73fe0848cab1d Mon Sep 17 00:00:00 2001 From: Mourjo Sen Date: Fri, 1 May 2020 18:19:55 +0530 Subject: [PATCH 01/10] When using test-ns-hook, ensure no NPE in junit reporter --- src/circleci/test/report/junit.clj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/circleci/test/report/junit.clj b/src/circleci/test/report/junit.clj index 95582ea..cad4393 100644 --- a/src/circleci/test/report/junit.clj +++ b/src/circleci/test/report/junit.clj @@ -33,8 +33,8 @@ (defn- testcase-elapsed [testcases] (->> testcases - (map (comp :time :attrs)) - (reduce +))) + (keep (comp :time :attrs)) + (apply +))) (defn- suite-xml [m testcases] From e784fab105f856211f713e4f1d372b9460a5f04a Mon Sep 17 00:00:00 2001 From: Mourjo Sen Date: Fri, 1 May 2020 10:52:29 +0530 Subject: [PATCH 02/10] Accept vars as input along with namespaces --- dev-resources/circleci_test/config.clj | 4 +- src/circleci/test.clj | 69 +++++++++++++++++++++++--- test/circleci/sample_test_ns1.clj | 22 ++++++++ test/circleci/sample_test_ns2.clj | 15 ++++++ 4 files changed, 102 insertions(+), 8 deletions(-) create mode 100644 test/circleci/sample_test_ns1.clj create mode 100644 test/circleci/sample_test_ns2.clj diff --git a/dev-resources/circleci_test/config.clj b/dev-resources/circleci_test/config.clj index be9096c..a499050 100644 --- a/dev-resources/circleci_test/config.clj +++ b/dev-resources/circleci_test/config.clj @@ -4,7 +4,9 @@ (def ^:dynamic *inside-global* false) {:selectors {:all (constantly true) - :default (complement :failing)} + :default (complement :failing) + :select-vars (fn [m] + (.endsWith (str (:name m)) "-2"))} :test-results-dir (or (System/getenv "CIRCLE_TEST_REPORTS") "test-results") :reporters [clojure-test-reporter junit/reporter] diff --git a/src/circleci/test.clj b/src/circleci/test.clj index 9b48ec4..b18886c 100644 --- a/src/circleci/test.clj +++ b/src/circleci/test.clj @@ -1,6 +1,7 @@ (ns circleci.test (:require [circleci.test.report :as report] [clojure.test :as test] + [clojure.string :as cs] [clojure.java.io :as io]) (:import (clojure.lang LineNumberingPushbackReader))) @@ -125,10 +126,32 @@ :when (and (:test (meta v)) (selector (meta v)))] v)) + (defn- test-all-vars [config ns selector] (doseq [v (get-all-vars config ns selector)] (test-var v config))) + +(defn copy-meta + [v from-key to-key] + (if-let [x (get (meta v) from-key)] + (alter-meta! v #(-> % (assoc to-key x) (dissoc from-key))))) + + +(defmacro with-unmarking + [ns var-selector & body] + `(let [vars# (vals (ns-interns ~ns))] + (try + (doseq [a-var# vars#] + (when (and (:test (meta a-var#)) + (not (~var-selector a-var#))) + (copy-meta a-var# :test ::skipped-test))) + ~@body + (finally + (doseq [a-var# vars#] + (copy-meta a-var# ::skipped-test :test)))))) + + (defn test-ns "The entry-point into circleci.test for running all tests in a namespace. @@ -176,6 +199,24 @@ @test/*report-counters*))) +(defn run-selected-var + [v selector config] + (binding [test/*report-counters* (ref test/*initial-report-counters*) + test/report report/report + report/*reporters* (get-reporters config)] + (let [n (.-ns v)] + (if-let [tnv (find-var (symbol (str (ns-name n)) + "test-ns-hook"))] + (with-unmarking n + (fn [a-var] (and (= a-var v) (-> a-var meta selector))) + ((var-get tnv))) + + (when (-> v meta selector) + (binding [test/test-var (partial test-var* config)] + (test-var* config v))))) + @test/*report-counters*)) + + ;; Running tests; high-level fns (defn- run-selected-tests @@ -183,12 +224,17 @@ Defaults to current namespace if none given. Returns a map summarizing test results." ([selector] (run-selected-tests selector [*ns*])) - ([selector nses] (run-selected-tests selector nses (read-config!))) - ([selector nses config] + ([selector nses] (run-selected-tests selector nses [])) + ([selector nses extra-vars] (run-selected-tests selector nses extra-vars (read-config!))) + ([selector nses extra-vars config] (let [global-fixture-fn (make-global-fixture config) summary (global-fixture-fn - #(assoc (apply merge-with + (for [n nses] - (test-ns n selector config))) + #(assoc (apply merge-with + + (concat + (for [n nses] + (test-ns n selector config)) + (for [v (set extra-vars)] + (run-selected-var v selector config)))) :type :summary))] (test/do-report summary) summary))) @@ -247,7 +293,16 @@ (when (empty? raw-args) (throw (ex-info "Must pass a list of namespaces to test" {}))) (let [config (read-config!) - [selector & nses] (read-args config raw-args) - _ (apply require :reload nses) - summary (run-selected-tests selector nses config)] + [selector & nses-or-vars] (read-args config raw-args) + {nses false vars true} (group-by #(.contains (str %) "/") nses-or-vars) + nses-set (set nses) + nses-from-vars (mapv #(symbol (first (cs/split (str %) #"/"))) vars) + test-nses (distinct (into nses nses-from-vars)) + _ (apply require :reload test-nses) + extra-vars (keep (fn [v] + (when-let [v (find-var (symbol v))] + (when-not (nses-set (ns-name (.-ns v))) + v))) + vars) + summary (run-selected-tests selector nses extra-vars config)] (System/exit (+ (:error summary) (:fail summary))))) diff --git a/test/circleci/sample_test_ns1.clj b/test/circleci/sample_test_ns1.clj new file mode 100644 index 0000000..f99c8b5 --- /dev/null +++ b/test/circleci/sample_test_ns1.clj @@ -0,0 +1,22 @@ +(ns circleci.sample-test-ns1 + (:require [clojure.test :refer :all])) + + +(deftest test-1 + (println "Running: circleci.sample-test-ns1/test-1") + (is (= 1 1))) + +(deftest test-2 + (println "Running: circleci.sample-test-ns1/test-2") + (is (= 10 10))) + +(deftest test-3 + (println "Running: circleci.sample-test-ns1/test-3") + (is (= 109 109))) + + +(defn test-ns-hook + [] + (test-1) + (test-2) + (test-3)) diff --git a/test/circleci/sample_test_ns2.clj b/test/circleci/sample_test_ns2.clj new file mode 100644 index 0000000..8c4aca4 --- /dev/null +++ b/test/circleci/sample_test_ns2.clj @@ -0,0 +1,15 @@ +(ns circleci.sample-test-ns2 + (:require [clojure.test :refer :all])) + + +(deftest test-1 + (println "Running: circleci.sample-test-ns2/test-1") + (is (= 1 1))) + +(deftest test-2 + (println "Running: circleci.sample-test-ns2/test-2") + (is (= 10 10))) + +(deftest test-3 + (println "Running: circleci.sample-test-ns2/test-3") + (is (= 109 109))) From f34ea41c67992224248e566025358f97a784e7f0 Mon Sep 17 00:00:00 2001 From: Mourjo Sen Date: Fri, 1 May 2020 22:42:37 +0530 Subject: [PATCH 03/10] When test-ns-hook is used, ensure that unselected tests don't run This behaviour is the same as with Leiningen's test selectors. --- src/circleci/test.clj | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/circleci/test.clj b/src/circleci/test.clj index b18886c..1cafe3a 100644 --- a/src/circleci/test.clj +++ b/src/circleci/test.clj @@ -183,7 +183,10 @@ ;; If the namespace has a test-ns-hook function, call that: (if-let [v (find-var (symbol (str (ns-name ns-obj)) "test-ns-hook"))] - ((var-get v)) + (with-unmarking ns + (fn [a-var] (-> a-var meta selector)) + ((var-get v))) + ;; Otherwise, just test every var in the namespace. (test-all-vars config ns-obj selector)))))) (catch Exception e From f0eb40d876107fbd11230176e46a07d703c4e2de Mon Sep 17 00:00:00 2001 From: Mourjo Sen Date: Sat, 2 May 2020 09:29:16 +0530 Subject: [PATCH 04/10] When test-ns-hook is used, do not double count tests When tests are run via test-ns-hook, clojure.test calls: (do-report {:type :begin-test-var, :var v}) (inc-report-counter :test) Which for circleci.test reports means that the test counter is incremented twice. --- src/circleci/test.clj | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/circleci/test.clj b/src/circleci/test.clj index 1cafe3a..ec23138 100644 --- a/src/circleci/test.clj +++ b/src/circleci/test.clj @@ -185,7 +185,8 @@ "test-ns-hook"))] (with-unmarking ns (fn [a-var] (-> a-var meta selector)) - ((var-get v))) + (binding [test/test-var (partial test-var* config)] + ((var-get v)))) ;; Otherwise, just test every var in the namespace. (test-all-vars config ns-obj selector)))))) @@ -212,7 +213,8 @@ "test-ns-hook"))] (with-unmarking n (fn [a-var] (and (= a-var v) (-> a-var meta selector))) - ((var-get tnv))) + (binding [test/test-var (partial test-var* config)] + ((var-get tnv)))) (when (-> v meta selector) (binding [test/test-var (partial test-var* config)] From 8ab2c3c87ee803a0b1ef14556823f6d59113cd12 Mon Sep 17 00:00:00 2001 From: Mourjo Sen Date: Sat, 2 May 2020 10:26:38 +0530 Subject: [PATCH 05/10] When a namespace or var is not found, continue testing with others --- src/circleci/test.clj | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/circleci/test.clj b/src/circleci/test.clj index ec23138..224bab9 100644 --- a/src/circleci/test.clj +++ b/src/circleci/test.clj @@ -3,7 +3,8 @@ [clojure.test :as test] [clojure.string :as cs] [clojure.java.io :as io]) - (:import (clojure.lang LineNumberingPushbackReader))) + (:import (clojure.lang LineNumberingPushbackReader) + java.io.FileNotFoundException)) ;; Once fixtures should be run exactly once regardless of which entry-point ;; into circleci.test is used @@ -234,12 +235,12 @@ ([selector nses extra-vars config] (let [global-fixture-fn (make-global-fixture config) summary (global-fixture-fn - #(assoc (apply merge-with + + #(assoc (apply merge-with + {:pass 0 :fail 0 :error 0} (concat - (for [n nses] + (for [n (distinct nses)] (test-ns n selector config)) - (for [v (set extra-vars)] - (run-selected-var v selector config)))) + (for [v (distinct extra-vars)] + (run-selected-var v selector config)))) :type :summary))] (test/do-report summary) summary))) @@ -303,11 +304,15 @@ nses-set (set nses) nses-from-vars (mapv #(symbol (first (cs/split (str %) #"/"))) vars) test-nses (distinct (into nses nses-from-vars)) - _ (apply require :reload test-nses) + whole-nses (filterv (fn [ns] + (try (require :reload ns) + (nses-set ns) + (catch FileNotFoundException _))) + test-nses) extra-vars (keep (fn [v] (when-let [v (find-var (symbol v))] (when-not (nses-set (ns-name (.-ns v))) v))) vars) - summary (run-selected-tests selector nses extra-vars config)] + summary (run-selected-tests selector whole-nses extra-vars config)] (System/exit (+ (:error summary) (:fail summary))))) From e5ee6791a09d291be1cadcc19fc6dabac45d0fef Mon Sep 17 00:00:00 2001 From: Mourjo Sen Date: Sat, 2 May 2020 10:50:13 +0530 Subject: [PATCH 06/10] Refactor commandline var selection code --- src/circleci/test.clj | 93 ++++++++++++++++++++++++++++--------------- 1 file changed, 62 insertions(+), 31 deletions(-) diff --git a/src/circleci/test.clj b/src/circleci/test.clj index 224bab9..002038a 100644 --- a/src/circleci/test.clj +++ b/src/circleci/test.clj @@ -203,13 +203,17 @@ (test/do-report {:type :end-test-ns, :ns ns-obj})))) @test/*report-counters*))) +(defn test-nses + [nses selector config] + (for [n (sort-by str (distinct nses))] + (test-ns n selector config))) -(defn run-selected-var +(defn test-selected-var [v selector config] (binding [test/*report-counters* (ref test/*initial-report-counters*) test/report report/report report/*reporters* (get-reporters config)] - (let [n (.-ns v)] + (let [n (-> v meta :ns)] (if-let [tnv (find-var (symbol (str (ns-name n)) "test-ns-hook"))] (with-unmarking n @@ -219,10 +223,22 @@ (when (-> v meta selector) (binding [test/test-var (partial test-var* config)] - (test-var* config v))))) + (test-var* config v))))) @test/*report-counters*)) +(defn test-vars-in-ns-groups + [vars selector config] + (let [ns-groups (group-by (comp :ns meta) (distinct vars)) + reports (for [ns (keys ns-groups)] + (try + (test/do-report {:type :begin-test-ns, :ns ns}) + (for [v (get ns-groups ns)] + (test-selected-var v selector config)) + (finally (test/do-report {:type :end-test-ns, :ns ns}))))] + (apply concat reports))) + + ;; Running tests; high-level fns (defn- run-selected-tests @@ -231,19 +247,23 @@ summarizing test results." ([selector] (run-selected-tests selector [*ns*])) ([selector nses] (run-selected-tests selector nses [])) - ([selector nses extra-vars] (run-selected-tests selector nses extra-vars (read-config!))) - ([selector nses extra-vars config] - (let [global-fixture-fn (make-global-fixture config) - summary (global-fixture-fn - #(assoc (apply merge-with + {:pass 0 :fail 0 :error 0} - (concat - (for [n (distinct nses)] - (test-ns n selector config)) - (for [v (distinct extra-vars)] - (run-selected-var v selector config)))) - :type :summary))] - (test/do-report summary) - summary))) + ([selector nses vars] (run-selected-tests selector nses vars (read-config!))) + ([selector nses vars config] + (if (and (empty? nses) (empty? vars)) + (let [summary {:type :summary :pass 0 :fail 0 :error 0 :test 0}] + (test/do-report summary) + summary) + + (let [global-fixture-fn (make-global-fixture config) + summary (global-fixture-fn + #(assoc (apply merge-with + {:pass 0 :fail 0 :error 0 :test 0} + (into + (test-nses nses selector config) + (test-vars-in-ns-groups vars selector config))) + :type :summary))] + + (test/do-report summary) + summary)))) (defn run-tests "Runs all tests in the given namespaces; prints results. @@ -294,25 +314,36 @@ summary (run-selected-tests selector nses)] (System/exit (+ (:error summary) (:fail summary)))))) -(defn -main - [& raw-args] - (when (empty? raw-args) - (throw (ex-info "Must pass a list of namespaces to test" {}))) - (let [config (read-config!) - [selector & nses-or-vars] (read-args config raw-args) - {nses false vars true} (group-by #(.contains (str %) "/") nses-or-vars) + +(defn segregate-nses-and-vars + "Given a list of namespaces and vars, separates them into namespaces + which are to be tested fully and individual vars. Also loads all + required namespaces." + [nses-or-vars] + (let [{nses false vars true} (group-by #(cs/includes? (str %) "/") nses-or-vars) nses-set (set nses) nses-from-vars (mapv #(symbol (first (cs/split (str %) #"/"))) vars) test-nses (distinct (into nses nses-from-vars)) whole-nses (filterv (fn [ns] - (try (require :reload ns) - (nses-set ns) - (catch FileNotFoundException _))) + (try (require :reload ns) + (nses-set ns) + (catch FileNotFoundException _))) test-nses) extra-vars (keep (fn [v] - (when-let [v (find-var (symbol v))] - (when-not (nses-set (ns-name (.-ns v))) - v))) - vars) - summary (run-selected-tests selector whole-nses extra-vars config)] + (try + (when-let [v (find-var (symbol v))] + (when-not (-> v meta :ns ns-name nses-set) + v)) + (catch IllegalArgumentException _))) + vars)] + [whole-nses extra-vars])) + +(defn -main + [& raw-args] + (when (empty? raw-args) + (throw (ex-info "Must pass a list of namespaces to test" {}))) + (let [config (read-config!) + [selector & nses-or-vars] (read-args config raw-args) + [nses vars] (segregate-nses-and-vars nses-or-vars) + summary (run-selected-tests selector nses vars config)] (System/exit (+ (:error summary) (:fail summary))))) From eaa89237445aac771484d5b007a6689ced35f232 Mon Sep 17 00:00:00 2001 From: Mourjo Sen Date: Sat, 2 May 2020 11:06:55 +0530 Subject: [PATCH 07/10] Add tests for fixtures with var selectors --- dev-resources/circleci_test/config.clj | 3 +- test/circleci/sample_test_ns1.clj | 43 ++++++++++++++-- test/circleci/sample_test_ns2.clj | 69 +++++++++++++++++++++++--- 3 files changed, 105 insertions(+), 10 deletions(-) diff --git a/dev-resources/circleci_test/config.clj b/dev-resources/circleci_test/config.clj index a499050..f109804 100644 --- a/dev-resources/circleci_test/config.clj +++ b/dev-resources/circleci_test/config.clj @@ -6,7 +6,8 @@ {:selectors {:all (constantly true) :default (complement :failing) :select-vars (fn [m] - (.endsWith (str (:name m)) "-2"))} + (.endsWith (str (:name m)) "-2")) + :combination :combination} :test-results-dir (or (System/getenv "CIRCLE_TEST_REPORTS") "test-results") :reporters [clojure-test-reporter junit/reporter] diff --git a/test/circleci/sample_test_ns1.clj b/test/circleci/sample_test_ns1.clj index f99c8b5..7b15b1f 100644 --- a/test/circleci/sample_test_ns1.clj +++ b/test/circleci/sample_test_ns1.clj @@ -1,18 +1,36 @@ (ns circleci.sample-test-ns1 (:require [clojure.test :refer :all])) +(def ^:dynamic vonce 0) +(def ^:dynamic veach 0) +(def ^:dynamic vcommon 0) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; This namespace's tests will fail with the Leiningen test runner ;; +;; because when there is a test-ns-hook, fixtures are NOT run by ;; +;; Leiningen or Clojure.test ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (deftest test-1 (println "Running: circleci.sample-test-ns1/test-1") - (is (= 1 1))) + (is (= 1 1)) + (is (= 1 veach)) + (is (= 1 vonce)) + (is (= 2 vcommon))) (deftest test-2 (println "Running: circleci.sample-test-ns1/test-2") - (is (= 10 10))) + (is (= 10 10)) + (is (= 1 veach)) + (is (= 1 vonce)) + (is (= 2 vcommon))) (deftest test-3 (println "Running: circleci.sample-test-ns1/test-3") - (is (= 109 109))) + (is (= 109 109)) + (is (= 1 veach)) + (is (= 1 vonce)) + (is (= 2 vcommon))) (defn test-ns-hook @@ -20,3 +38,22 @@ (test-1) (test-2) (test-3)) + + +(defn each-fixture + [f] + (binding [veach (inc veach) + vcommon (inc vcommon)] + (f))) + + +(defn once-fixture + [f] + (binding [vonce (inc vonce) + vcommon (inc vcommon)] + (f))) + + + +(use-fixtures :each each-fixture) +(use-fixtures :once once-fixture) diff --git a/test/circleci/sample_test_ns2.clj b/test/circleci/sample_test_ns2.clj index 8c4aca4..0b04835 100644 --- a/test/circleci/sample_test_ns2.clj +++ b/test/circleci/sample_test_ns2.clj @@ -1,15 +1,72 @@ (ns circleci.sample-test-ns2 (:require [clojure.test :refer :all])) +(def ^:dynamic vonce 0) +(def ^:dynamic veach 0) +(def ^:dynamic vcommon 0) +(def ^:dynamic level-of-nesting 0) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; This namespace fails on Leiningen tests as Leiningen does not run ;; +;; each-fixture more than once even when a test calls another ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + (deftest test-1 - (println "Running: circleci.sample-test-ns2/test-1") - (is (= 1 1))) + (when (zero? level-of-nesting) + (println "Running: circleci.sample-test-ns2/test-1")) + (is (= 1 1)) + (is (= (+ level-of-nesting 1) veach)) + (is (= 1 vonce)) + (is (= (+ level-of-nesting 2) vcommon))) (deftest test-2 - (println "Running: circleci.sample-test-ns2/test-2") - (is (= 10 10))) + (when (zero? level-of-nesting) + (println "Running: circleci.sample-test-ns2/test-2")) + (is (= 10 10)) + (is (= (+ level-of-nesting 1) veach)) + (is (= 1 vonce)) + (is (= (+ level-of-nesting 2) vcommon))) (deftest test-3 - (println "Running: circleci.sample-test-ns2/test-3") - (is (= 109 109))) + (when (zero? level-of-nesting) + (println "Running: circleci.sample-test-ns2/test-3")) + (is (= 109 109)) + (is (= (+ level-of-nesting 1) veach)) + (is (= 1 vonce)) + (is (= (+ level-of-nesting 2) vcommon))) + +(deftest ^:combination test-4 + (when (zero? level-of-nesting) + (println "Running: circleci.sample-test-ns2/test-4")) + (binding [level-of-nesting (inc level-of-nesting)] + (test-1) + (test-2) + (test-3))) + +(deftest ^:combination test-5 + (println "Running: circleci.sample-test-ns2/test-5") + (binding [level-of-nesting (inc level-of-nesting)] + (test-1) + (test-2) + (test-3) + (test-4))) + + +(defn each-fixture + [f] + (binding [veach (inc veach) + vcommon (inc vcommon)] + (f))) + + +(defn once-fixture + [f] + (binding [vonce (inc vonce) + vcommon (inc vcommon)] + (f))) + + + +(use-fixtures :each each-fixture) +(use-fixtures :once once-fixture) From 2d35e34e079863e12320f33726b61c2e03e86b20 Mon Sep 17 00:00:00 2001 From: Mourjo Sen Date: Sat, 2 May 2020 12:15:03 +0530 Subject: [PATCH 08/10] Ensure each fixtures are called atmost once for a test This behaviour is similar to Leiningen and Clojure test where if a test calls another test, the once and each fixtures are called only once. --- src/circleci/test.clj | 52 +++++++++++++++---------------- test/circleci/sample_test_ns2.clj | 19 ++++------- 2 files changed, 32 insertions(+), 39 deletions(-) diff --git a/src/circleci/test.clj b/src/circleci/test.clj index 002038a..fd33a07 100644 --- a/src/circleci/test.clj +++ b/src/circleci/test.clj @@ -17,14 +17,10 @@ ;; This means test-var must attempt to run once fixtures each time it is ;; invoked. ;; -;; To avoid constantly recalculating once fixtures we map the ns to a -;; fixture-generating function. -;; When running once fixtures we look up the fixture generating fn and invoke -;; it to produce the once-fixtures-fn. -;; Before invoking the generated once-fixtures-fn we bind a new mapping from -;; the ns the test var belongs to to a fixture generating fn that produces a -;; dummy once-fixture. -(def ^:dynamic *once-fixtures* {}) +;; Keep track of whether for you are inside a form which has already +;; run the fixture you want. That is, no chain of function calls +;; should have a fixture twice. +(def ^:dynamic *fixtures* {}) (def ^:private default-config {:test-results-dir "test-results" :reporters [report/clojure-test-reporter]}) @@ -36,27 +32,31 @@ {})] (merge default-config config))) -(defn- make-once-fixture-fn +(defn- make-once-fixture [ns] - (test/join-fixtures (::test/once-fixtures (meta ns)))) + (fn [f] + (if (get-in *fixtures* [:once ns]) + (f) + (binding [*fixtures* (assoc-in *fixtures* [:once ns] true)] + (let [fix-fn (test/join-fixtures (::test/once-fixtures (meta ns)))] + (fix-fn f)))))) -(defn- once-fixtures +(defn- make-each-fixture [ns] (fn [f] - (let [make-once-fixtures (get *once-fixtures* ns make-once-fixture-fn)] - (binding [*once-fixtures* (assoc *once-fixtures* - ns - (fn [_] - (fn [x] (x))))] - ((make-once-fixtures ns) f))))) - -(def ^:private ^:dynamic *inside-global-fixtures?* false) + (if (get-in *fixtures* [:each ns]) + (f) + (binding [*fixtures* (assoc-in *fixtures* [:each ns] true)] + (let [fix-fn (test/join-fixtures (::test/each-fixtures (meta ns)))] + (fix-fn f)))))) -(defn make-global-fixture [{:keys [global-fixture]}] +(defn make-global-fixture + [{:keys [global-fixture] + :or {global-fixture (fn [f] (f))}}] (fn [f] - (if (or *inside-global-fixtures?* (not global-fixture)) + (if (get *fixtures* :global) (f) - (binding [*inside-global-fixtures?* true] + (binding [*fixtures* (assoc *fixtures* :global true)] (global-fixture f))))) ;; Running tests; low-level fns @@ -81,8 +81,8 @@ (assert (var? v) (format "v must be a var. got %s" (class v))) (let [ns (-> v meta :ns) global-fixture-fn (make-global-fixture config) - once-fixture-fn (once-fixtures ns) - each-fixture-fn (test/join-fixtures (::test/each-fixtures (meta ns)))] + once-fixture-fn (make-once-fixture ns) + each-fixture-fn (make-each-fixture ns)] (when (:test (meta v)) (binding [test/*testing-vars* (conj test/*testing-vars* v)] (let [start-time (System/nanoTime)] @@ -173,8 +173,8 @@ run-once-fixture? (seq (get-all-vars config ns selector)) global-fixture-fn (make-global-fixture config) once-fixture-fn (if run-once-fixture? - (once-fixtures ns-obj) - (fn [f] ((make-once-fixture-fn ns) f)))] + (make-once-fixture ns-obj) + (fn [f] (f)))] (try (global-fixture-fn (fn [] diff --git a/test/circleci/sample_test_ns2.clj b/test/circleci/sample_test_ns2.clj index 0b04835..861430b 100644 --- a/test/circleci/sample_test_ns2.clj +++ b/test/circleci/sample_test_ns2.clj @@ -6,35 +6,29 @@ (def ^:dynamic vcommon 0) (def ^:dynamic level-of-nesting 0) -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; This namespace fails on Leiningen tests as Leiningen does not run ;; -;; each-fixture more than once even when a test calls another ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - - (deftest test-1 (when (zero? level-of-nesting) (println "Running: circleci.sample-test-ns2/test-1")) (is (= 1 1)) - (is (= (+ level-of-nesting 1) veach)) + (is (= 1 veach)) (is (= 1 vonce)) - (is (= (+ level-of-nesting 2) vcommon))) + (is (= 2 vcommon))) (deftest test-2 (when (zero? level-of-nesting) (println "Running: circleci.sample-test-ns2/test-2")) (is (= 10 10)) - (is (= (+ level-of-nesting 1) veach)) + (is (= 1 veach)) (is (= 1 vonce)) - (is (= (+ level-of-nesting 2) vcommon))) + (is (= 2 vcommon))) (deftest test-3 (when (zero? level-of-nesting) (println "Running: circleci.sample-test-ns2/test-3")) (is (= 109 109)) - (is (= (+ level-of-nesting 1) veach)) + (is (= 1 veach)) (is (= 1 vonce)) - (is (= (+ level-of-nesting 2) vcommon))) + (is (= 2 vcommon))) (deftest ^:combination test-4 (when (zero? level-of-nesting) @@ -67,6 +61,5 @@ (f))) - (use-fixtures :each each-fixture) (use-fixtures :once once-fixture) From 4fc6d361d09d130bdd8c4ae0d6a6824445896dc2 Mon Sep 17 00:00:00 2001 From: Mourjo Sen Date: Sat, 2 May 2020 14:59:20 +0530 Subject: [PATCH 09/10] Do not run fixtures in namespaces when using test-ns-hook This is in accordance with clojure.test's definition of fixtures and test-ns-hook: Note: Fixtures and test-ns-hook are mutually incompatible. If you are using test-ns-hook, fixture functions will *never* be run. Global fixtures still run. --- src/circleci/test.clj | 89 ++++++++++++++++++++----------- test/circleci/sample_test_ns1.clj | 24 ++++----- 2 files changed, 68 insertions(+), 45 deletions(-) diff --git a/src/circleci/test.clj b/src/circleci/test.clj index fd33a07..dcc980c 100644 --- a/src/circleci/test.clj +++ b/src/circleci/test.clj @@ -103,6 +103,27 @@ :var v :elapsed elapsed}))))))))) + +(defn- test-var-with-ns-hook* + [config v] + (assert (var? v) (format "v must be a var. got %s" (class v))) + (let [global-fixture-fn (make-global-fixture config)] + (when (:test (meta v)) + (binding [test/*testing-vars* (conj test/*testing-vars* v)] + (let [start-time (System/nanoTime)] + (try + (global-fixture-fn (fn [] (test* v))) + (catch Exception e + (test/do-report {:type :error, + :message "Uncaught exception, not in assertion." + :expected nil, :actual e})) + (finally + (let [stop-time (System/nanoTime) + elapsed (-> stop-time (- start-time) nanos->seconds)] + (test/do-report {:type :end-test-var, + :var v + :elapsed elapsed}))))))))) + (defn test-var "The entry-point into circleci.test for running a single test. @@ -129,7 +150,7 @@ (defn- test-all-vars [config ns selector] - (doseq [v (get-all-vars config ns selector)] + (doseq [v (sort-by str (get-all-vars config ns selector))] (test-var v config))) @@ -139,15 +160,21 @@ (alter-meta! v #(-> % (assoc to-key x) (dissoc from-key))))) -(defmacro with-unmarking - [ns var-selector & body] - `(let [vars# (vals (ns-interns ~ns))] +(defmacro select-test-ns-hook + "When test-ns-hook is used, select vars based on the selector but + don't run once and each fixtures." + [ns-hook var-selector config] + `(let [ns# (-> ~ns-hook meta :ns) + vars# (vals (ns-interns ns#))] (try (doseq [a-var# vars#] (when (and (:test (meta a-var#)) (not (~var-selector a-var#))) (copy-meta a-var# :test ::skipped-test))) - ~@body + + (binding [test/test-var (partial test-var-with-ns-hook* ~config)] + ((var-get ~ns-hook))) + (finally (doseq [a-var# vars#] (copy-meta a-var# ::skipped-test :test)))))) @@ -170,32 +197,33 @@ test/report report/report report/*reporters* (get-reporters config)] (let [ns-obj (the-ns ns) - run-once-fixture? (seq (get-all-vars config ns selector)) + ns-hook (find-var (symbol (str (ns-name ns-obj)) + "test-ns-hook")) + run-once-fixture? (when-not ns-hook + (seq (get-all-vars config ns selector))) global-fixture-fn (make-global-fixture config) once-fixture-fn (if run-once-fixture? (make-once-fixture ns-obj) (fn [f] (f)))] (try (global-fixture-fn - (fn [] - (once-fixture-fn - (fn [] - (test/do-report {:type :begin-test-ns, :ns ns-obj}) - ;; If the namespace has a test-ns-hook function, call that: - (if-let [v (find-var (symbol (str (ns-name ns-obj)) - "test-ns-hook"))] - (with-unmarking ns - (fn [a-var] (-> a-var meta selector)) - (binding [test/test-var (partial test-var* config)] - ((var-get v)))) - - ;; Otherwise, just test every var in the namespace. - (test-all-vars config ns-obj selector)))))) + (fn [] + (once-fixture-fn + (fn [] + (test/do-report {:type :begin-test-ns, :ns ns-obj}) + ;; If the namespace has a test-ns-hook function, call that: + (if ns-hook + (select-test-ns-hook ns-hook + (fn [a-var] (-> a-var meta selector)) + config) + + ;; Otherwise, just test every var in the namespace. + (test-all-vars config ns-obj selector)))))) (catch Exception e (binding [test/*testing-vars* (conj test/*testing-vars* (with-meta 'test - {:name "Exception thrown from test fixture" - :ns ns-obj}))] + {:name "Exception thrown from test fixture" + :ns ns-obj}))] (test/do-report {:type :error, :message "Exception thrown from test fixture." :expected nil, :actual e}))) @@ -208,18 +236,19 @@ (for [n (sort-by str (distinct nses))] (test-ns n selector config))) + + (defn test-selected-var [v selector config] (binding [test/*report-counters* (ref test/*initial-report-counters*) test/report report/report report/*reporters* (get-reporters config)] (let [n (-> v meta :ns)] - (if-let [tnv (find-var (symbol (str (ns-name n)) - "test-ns-hook"))] - (with-unmarking n - (fn [a-var] (and (= a-var v) (-> a-var meta selector))) - (binding [test/test-var (partial test-var* config)] - ((var-get tnv)))) + (if-let [ns-hook (find-var (symbol (str (ns-name n)) + "test-ns-hook"))] + (select-test-ns-hook ns-hook + (fn [a-var] (and (= a-var v) (-> a-var meta selector))) + config) (when (-> v meta selector) (binding [test/test-var (partial test-var* config)] @@ -230,10 +259,10 @@ (defn test-vars-in-ns-groups [vars selector config] (let [ns-groups (group-by (comp :ns meta) (distinct vars)) - reports (for [ns (keys ns-groups)] + reports (for [ns (sort-by str (keys ns-groups))] (try (test/do-report {:type :begin-test-ns, :ns ns}) - (for [v (get ns-groups ns)] + (for [v (sort-by str (get ns-groups ns))] (test-selected-var v selector config)) (finally (test/do-report {:type :end-test-ns, :ns ns}))))] (apply concat reports))) diff --git a/test/circleci/sample_test_ns1.clj b/test/circleci/sample_test_ns1.clj index 7b15b1f..2d69ef8 100644 --- a/test/circleci/sample_test_ns1.clj +++ b/test/circleci/sample_test_ns1.clj @@ -5,32 +5,26 @@ (def ^:dynamic veach 0) (def ^:dynamic vcommon 0) -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; This namespace's tests will fail with the Leiningen test runner ;; -;; because when there is a test-ns-hook, fixtures are NOT run by ;; -;; Leiningen or Clojure.test ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - (deftest test-1 (println "Running: circleci.sample-test-ns1/test-1") (is (= 1 1)) - (is (= 1 veach)) - (is (= 1 vonce)) - (is (= 2 vcommon))) + (is (zero? veach)) + (is (zero? vonce)) + (is (zero? vcommon))) (deftest test-2 (println "Running: circleci.sample-test-ns1/test-2") (is (= 10 10)) - (is (= 1 veach)) - (is (= 1 vonce)) - (is (= 2 vcommon))) + (is (zero? veach)) + (is (zero? vonce)) + (is (zero? vcommon))) (deftest test-3 (println "Running: circleci.sample-test-ns1/test-3") (is (= 109 109)) - (is (= 1 veach)) - (is (= 1 vonce)) - (is (= 2 vcommon))) + (is (zero? veach)) + (is (zero? vonce)) + (is (zero? vcommon))) (defn test-ns-hook From 999bd2b3621e5ffd718e53b4c79ee06e5dd75fd0 Mon Sep 17 00:00:00 2001 From: Mourjo Sen Date: Sat, 2 May 2020 15:52:13 +0530 Subject: [PATCH 10/10] Add a sample project to test selectors --- .gitignore | 6 + Makefile | 19 ++++ dev-resources/weasley/circleci.test.version | 1 + .../dev-resources/circleci_test/config.clj | 24 ++++ dev-resources/weasley/project.clj | 11 ++ dev-resources/weasley/src/weasley/core.clj | 7 ++ .../weasley/test/weasley/sample_test_ns1.clj | 53 +++++++++ .../weasley/test/weasley/sample_test_ns2.clj | 65 +++++++++++ .../weasley/test/weasley/sample_test_ns3.clj | 73 +++++++++++++ test.sh | 103 ++++++++++++++++++ 10 files changed, 362 insertions(+) create mode 100644 Makefile create mode 100644 dev-resources/weasley/circleci.test.version create mode 100644 dev-resources/weasley/dev-resources/circleci_test/config.clj create mode 100644 dev-resources/weasley/project.clj create mode 100644 dev-resources/weasley/src/weasley/core.clj create mode 100644 dev-resources/weasley/test/weasley/sample_test_ns1.clj create mode 100644 dev-resources/weasley/test/weasley/sample_test_ns2.clj create mode 100644 dev-resources/weasley/test/weasley/sample_test_ns3.clj create mode 100644 test.sh diff --git a/.gitignore b/.gitignore index 3a5727f..3f1bd18 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,9 @@ pom.xml.asc .hgignore .hg/ /test-results/ +dev-resources/weasley/target/ +dev-resources/weasley/.lein-failures +dev-resources/weasley/test-results/ +dev-resources/weasley/.lein-repl-history +test_out.txt +dev-resources/weasley/test_out.txt diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d60c3db --- /dev/null +++ b/Makefile @@ -0,0 +1,19 @@ +weasley-test: root-test + @echo "------------------------------------" + @echo "Testing internal project Weasley" + @echo "------------------------------------" + + # The goal is to compare test runs with Leiningen where + # possible (is there a better way than this?) + sh test.sh + +root-test: + @echo "------------------------------------" + @echo "Testing root project circleci.test" + @echo "------------------------------------" + lein do clean, compile + lein test + +test: root-test + +.PHONY: test diff --git a/dev-resources/weasley/circleci.test.version b/dev-resources/weasley/circleci.test.version new file mode 100644 index 0000000..525706f --- /dev/null +++ b/dev-resources/weasley/circleci.test.version @@ -0,0 +1 @@ +(def circleci-test-version "0.4.3") diff --git a/dev-resources/weasley/dev-resources/circleci_test/config.clj b/dev-resources/weasley/dev-resources/circleci_test/config.clj new file mode 100644 index 0000000..f9dc960 --- /dev/null +++ b/dev-resources/weasley/dev-resources/circleci_test/config.clj @@ -0,0 +1,24 @@ +(require '[circleci.test.report :refer (clojure-test-reporter)]) +(require '[circleci.test.report.junit :as junit]) +(require '[clojure.java.io :as io]) + +(def ^:dynamic *global-counter* 0) + +{:selectors {:all (constantly true) + :default (complement :failing) + :select-vars (fn [m] + (.endsWith (str (:name m)) "-2")) + :combination :combination} + :test-results-dir (or (System/getenv "CIRCLE_TEST_REPORTS") + "test-results") + :reporters [clojure-test-reporter junit/reporter] + :global-fixture (fn [f] + (try + (io/delete-file "global_fixture_test.out" true) + (assert (zero? *global-counter*)) + (binding [*global-counter* (inc *global-counter*)] + (spit "global_fixture_test.out" *global-counter* :append true) + (f)) + (finally + (io/delete-file "global_fixture_test.out" true) + (assert (false? (.exists (clojure.java.io/file "global_fixture_test.out")))))))} diff --git a/dev-resources/weasley/project.clj b/dev-resources/weasley/project.clj new file mode 100644 index 0000000..c41feaa --- /dev/null +++ b/dev-resources/weasley/project.clj @@ -0,0 +1,11 @@ +(load-file "./circleci.test.version") +(defproject circleci/weasley "0.1.0-SNAPSHOT" + :dependencies [[org.clojure/clojure "1.10.1"] + [circleci/circleci.test ~circleci-test-version]] + :target-path "target/%s" + :profiles {:uberjar {:aot :all}} + :main weasley.core + :aot [weasley.core] + :aliases {"test" ["run" "-m" "circleci.test/dir" :project/test-paths] + "tests" ["run" "-m" "circleci.test"] + "retest" ["run" "-m" "circleci.test.retest"]}) diff --git a/dev-resources/weasley/src/weasley/core.clj b/dev-resources/weasley/src/weasley/core.clj new file mode 100644 index 0000000..5131b5d --- /dev/null +++ b/dev-resources/weasley/src/weasley/core.clj @@ -0,0 +1,7 @@ +(ns weasley.core + (:gen-class)) + +(defn -main + "I don't do a whole lot ... yet." + [& args] + (println "Hello, World!")) diff --git a/dev-resources/weasley/test/weasley/sample_test_ns1.clj b/dev-resources/weasley/test/weasley/sample_test_ns1.clj new file mode 100644 index 0000000..4d34d39 --- /dev/null +++ b/dev-resources/weasley/test/weasley/sample_test_ns1.clj @@ -0,0 +1,53 @@ +(ns weasley.sample-test-ns1 + (:require [clojure.test :refer :all])) + +(def ^:dynamic vonce 0) +(def ^:dynamic veach 0) +(def ^:dynamic vcommon 0) + +(deftest test-1 + (println "Running: circleci.sample-test-ns1/test-1") + (is (= 1 1)) + (is (zero? veach)) + (is (zero? vonce)) + (is (zero? vcommon))) + +(deftest test-2 + (println "Running: circleci.sample-test-ns1/test-2") + (is (= 10 10)) + (is (zero? veach)) + (is (zero? vonce)) + (is (zero? vcommon))) + +(deftest test-3 + (println "Running: circleci.sample-test-ns1/test-3") + (is (= 109 109)) + (is (zero? veach)) + (is (zero? vonce)) + (is (zero? vcommon))) + + +(defn test-ns-hook + [] + (test-1) + (test-2) + (test-3)) + + +(defn each-fixture + [f] + (binding [veach (inc veach) + vcommon (inc vcommon)] + (f))) + + +(defn once-fixture + [f] + (binding [vonce (inc vonce) + vcommon (inc vcommon)] + (f))) + + + +(use-fixtures :each each-fixture) +(use-fixtures :once once-fixture) diff --git a/dev-resources/weasley/test/weasley/sample_test_ns2.clj b/dev-resources/weasley/test/weasley/sample_test_ns2.clj new file mode 100644 index 0000000..c979d1a --- /dev/null +++ b/dev-resources/weasley/test/weasley/sample_test_ns2.clj @@ -0,0 +1,65 @@ +(ns weasley.sample-test-ns2 + (:require [clojure.test :refer :all])) + +(def ^:dynamic vonce 0) +(def ^:dynamic veach 0) +(def ^:dynamic vcommon 0) +(def ^:dynamic level-of-nesting 0) + +(deftest test-1 + (when (zero? level-of-nesting) + (println "Running: circleci.sample-test-ns2/test-1")) + (is (= 1 1)) + (is (= 1 veach)) + (is (= 1 vonce)) + (is (= 2 vcommon))) + +(deftest test-2 + (when (zero? level-of-nesting) + (println "Running: circleci.sample-test-ns2/test-2")) + (is (= 10 10)) + (is (= 1 veach)) + (is (= 1 vonce)) + (is (= 2 vcommon))) + +(deftest test-3 + (when (zero? level-of-nesting) + (println "Running: circleci.sample-test-ns2/test-3")) + (is (= 109 109)) + (is (= 1 veach)) + (is (= 1 vonce)) + (is (= 2 vcommon))) + +(deftest ^:combination test-4 + (when (zero? level-of-nesting) + (println "Running: circleci.sample-test-ns2/test-4")) + (binding [level-of-nesting (inc level-of-nesting)] + (test-1) + (test-2) + (test-3))) + +(deftest ^:combination test-5 + (println "Running: circleci.sample-test-ns2/test-5") + (binding [level-of-nesting (inc level-of-nesting)] + (test-1) + (test-2) + (test-3) + (test-4))) + + +(defn each-fixture + [f] + (binding [veach (inc veach) + vcommon (inc vcommon)] + (f))) + + +(defn once-fixture + [f] + (binding [vonce (inc vonce) + vcommon (inc vcommon)] + (f))) + + +(use-fixtures :each each-fixture) +(use-fixtures :once once-fixture) diff --git a/dev-resources/weasley/test/weasley/sample_test_ns3.clj b/dev-resources/weasley/test/weasley/sample_test_ns3.clj new file mode 100644 index 0000000..00cf9a9 --- /dev/null +++ b/dev-resources/weasley/test/weasley/sample_test_ns3.clj @@ -0,0 +1,73 @@ +(ns ^:global-fixture weasley.sample-test-ns3 + (:require [clojure.test :refer :all])) + +(def ^:dynamic vonce 0) +(def ^:dynamic veach 0) +(def ^:dynamic vcommon 0) +(def ^:dynamic level-of-nesting 0) + +(defn global-fixture-file + [] + (slurp "global_fixture_test.out")) + +(deftest test-1 + (when (zero? level-of-nesting) + (println "Running: circleci.sample-test-ns3/test-1")) + (is (= 1 veach)) + (is (= 1 vonce)) + (is (= 2 vcommon)) + (is (= "1" (global-fixture-file)))) + +(deftest test-2 + (when (zero? level-of-nesting) + (println "Running: circleci.sample-test-ns3/test-2")) + (is (= 1 veach)) + (is (= 1 vonce)) + (is (= 2 vcommon)) + (is (= "1" (global-fixture-file)))) + +(deftest test-3 + (when (zero? level-of-nesting) + (println "Running: circleci.sample-test-ns3/test-3")) + (is (= 1 veach)) + (is (= 1 vonce)) + (is (= 2 vcommon)) + (is (= "1" (global-fixture-file)))) + +(deftest ^:combination test-4 + (when (zero? level-of-nesting) + (println "Running: circleci.sample-test-ns3/test-4")) + (binding [level-of-nesting (inc level-of-nesting)] + (test-1) + (test-2) + (test-3) + (assert (= "1" (global-fixture-file))))) + +(deftest ^:combination test-5 + (println "Running: circleci.sample-test-ns3/test-5") + (binding [level-of-nesting (inc level-of-nesting)] + (test-1) + (test-2) + (test-3) + (test-4) + (assert (= "1" (global-fixture-file))))) + + +(defn each-fixture + [f] + (binding [veach (inc veach) + vcommon (inc vcommon)] + (assert (= "1" (global-fixture-file))) + (f))) + + +(defn once-fixture + [f] + (binding [vonce (inc vonce) + vcommon (inc vcommon)] + (assert (= "1" (global-fixture-file))) + (f))) + + +(use-fixtures :each each-fixture) +(use-fixtures :once once-fixture) diff --git a/test.sh b/test.sh new file mode 100644 index 0000000..c623845 --- /dev/null +++ b/test.sh @@ -0,0 +1,103 @@ +grep defproject project.clj | cut -d" " -f3 | xargs -I {} echo "(def circleci-test-version \"{}\")" > dev-resources/weasley/circleci.test.version + +lein install + +cd dev-resources/weasley/ + +lein do clean, compile + +# Counts between leiningen and circleci are off because of tests with global fixtures (ns3) +lein test > test_out.txt && +grep "Ran 33 tests containing 108 assertions." test_out.txt && +lein update-in :aliases empty -- update-in : assoc :test-selectors '{:default (complement :global-fixture)}' -- test > test_out.txt && +grep "Ran 18 tests containing 60 assertions." test_out.txt && + +lein tests weasley.sample-test-ns1 weasley.sample-test-ns2 > test_out.txt && +grep "Ran 18 tests containing 60 assertions." test_out.txt && +lein update-in :aliases empty -- test :only weasley.sample-test-ns1 weasley.sample-test-ns2 > test_out.txt && +grep "Ran 18 tests containing 60 assertions." test_out.txt && + +lein tests weasley.sample-test-ns1 > test_out.txt && +grep "Ran 3 tests containing 12 assertions." test_out.txt && +lein update-in :aliases empty -- test :only weasley.sample-test-ns1 > test_out.txt && +grep "Ran 3 tests containing 12 assertions." test_out.txt && + +lein tests weasley.sample-test-ns2 > test_out.txt && +grep "Ran 15 tests containing 48 assertions." test_out.txt && +lein update-in :aliases empty -- test :only weasley.sample-test-ns2 > test_out.txt && +grep "Ran 15 tests containing 48 assertions." test_out.txt && + +lein tests weasley.sample-test-ns2 weasley.sample-test-ns2 weasley.sample-test-ns2 weasley.sample-test-ns2 > test_out.txt && +grep "Ran 15 tests containing 48 assertions." test_out.txt && +lein update-in :aliases empty -- test :only weasley.sample-test-ns2 weasley.sample-test-ns2 weasley.sample-test-ns2 > test_out.txt && +grep "Ran 15 tests containing 48 assertions." test_out.txt && + +lein tests x y/z > test_out.txt && +grep "Ran 0 tests containing 0 assertions." test_out.txt && +lein update-in :aliases empty -- test :only x y/z > test_out.txt && +grep "Ran 0 tests containing 0 assertions." test_out.txt && + +lein tests weasley.sample-test-ns2 weasley.sample-test-ns1/test-1 x y/z > test_out.txt && +grep "Ran 16 tests containing 52 assertions." test_out.txt && +lein update-in :aliases empty -- test :only weasley.sample-test-ns2 weasley.sample-test-ns1/test-1 x y/z > test_out.txt && +grep "Ran 16 tests containing 52 assertions." test_out.txt && + +lein tests weasley.sample-test-ns2/test-1 > test_out.txt && +grep "Ran 1 tests containing 4 assertions." test_out.txt && +lein update-in :aliases empty -- test :only weasley.sample-test-ns2/test-1 > test_out.txt && +grep "Ran 1 tests containing 4 assertions." test_out.txt && + +lein tests weasley.sample-test-ns2/test-1 weasley.sample-test-ns2/test-2 > test_out.txt && +grep "Ran 2 tests containing 8 assertions." test_out.txt && +lein update-in :aliases empty -- test :only weasley.sample-test-ns2/test-1 weasley.sample-test-ns2/test-2 > test_out.txt && +grep "Ran 2 tests containing 8 assertions." test_out.txt && + +lein tests weasley.sample-test-ns2/test-1 weasley.sample-test-ns2 weasley.sample-test-ns2/test-2 weasley.sample-test-ns2/test-1 > test_out.txt && +grep "Ran 15 tests containing 48 assertions." test_out.txt && +lein update-in :aliases empty -- test :only weasley.sample-test-ns2/test-1 weasley.sample-test-ns2 weasley.sample-test-ns2/test-2 weasley.sample-test-ns2/test-1 > test_out.txt && +grep "Ran 15 tests containing 48 assertions." test_out.txt && + +lein tests :select-vars weasley.sample-test-ns2 > test_out.txt && +grep "Ran 1 tests containing 4 assertions." test_out.txt && +lein update-in :aliases empty -- test :only weasley.sample-test-ns2/test-2 > test_out.txt && +grep "Ran 1 tests containing 4 assertions." test_out.txt && + +lein tests :select-vars weasley.sample-test-ns1 > test_out.txt && +grep "Ran 1 tests containing 4 assertions." test_out.txt && +lein update-in :aliases empty -- test :only weasley.sample-test-ns1/test-2 > test_out.txt && +grep "Ran 1 tests containing 4 assertions." test_out.txt && + +# The equivalent run for this in Leiningen does not work (test-ns-hook) +lein tests :combination weasley.sample-test-ns2 > test_out.txt && +grep "Ran 12 tests containing 36 assertions." test_out.txt && + +# The equivalent run for this in Leiningen does not work (test calling another test) +lein tests :combination weasley.sample-test-ns2/test-4 weasley.sample-test-ns2/test-5 weasley.sample-test-ns2/test-1 > test_out.txt && +grep "Ran 12 tests containing 36 assertions." test_out.txt && + +lein tests :combination weasley.sample-test-ns1 > test_out.txt && +grep "Ran 0 tests containing 0 assertions." test_out.txt && +lein update-in :aliases empty -- update-in : assoc :test-selectors '{:combination :combination}' -- test weasley.sample-test-ns1 :combination > test_out.txt && +grep "Ran 0 tests containing 0 assertions." test_out.txt && + +# The equivalent run for this in Leiningen does not work (test calling another test) +lein tests :combination weasley.sample-test-ns2/test-4 > test_out.txt && +grep "Ran 4 tests containing 12 assertions." test_out.txt && + +# Global fixtures tests +lein tests weasley.sample-test-ns3 > test_out.txt && +grep "Ran 15 tests containing 48 assertions." test_out.txt && + +lein tests weasley.sample-test-ns3/test-1 > test_out.txt && +grep "Ran 1 tests containing 4 assertions." test_out.txt && + +lein tests weasley.sample-test-ns3/test-1 weasley.sample-test-ns3/test-2 > test_out.txt && +grep "Ran 2 tests containing 8 assertions." test_out.txt && + +lein tests :select-vars weasley.sample-test-ns3/test-1 weasley.sample-test-ns3/test-2 > test_out.txt && +grep "Ran 1 tests containing 4 assertions." test_out.txt && + +lein tests :combination weasley.sample-test-ns3 > test_out.txt && +grep "Ran 12 tests containing 36 assertions." test_out.txt && + +rm -f test_out.txt