|
2 | 2 | (:require
|
3 | 3 | [clojure.java.classpath :as classpath]
|
4 | 4 | [clojure.java.io :as io]
|
| 5 | + [clojure.math :as math] |
5 | 6 | [clojure.pprint :as pprint]
|
6 | 7 | [clojure.set :as set]
|
7 | 8 | [clojure.string :as str]
|
|
120 | 121 | [_nil options]
|
121 | 122 | (find-tests (classpath/system-classpath) options))
|
122 | 123 |
|
| 124 | +(defn- partition-all-into-n-partitions |
| 125 | + "Split sequence `xs` into `num-partitions` as equally as possible. Guaranteed to return `num-partitions`. This custom |
| 126 | + function is used instead of [[partition-all]] or whatever because we want to make sure every partition gets tests, |
| 127 | + even with weird combinations like 4 tests with 3 partitions or 29 tests with 10 partitions." |
| 128 | + [num-partitions xs] |
| 129 | + {:post [(= (count %) num-partitions)]} |
| 130 | + ;; make sure the partitioning is deterministic -- `xs` should always come back in the same order but we should sort |
| 131 | + ;; just to be safe. |
| 132 | + (let [xs (sort-by str xs) |
| 133 | + partition-size (/ (count xs) num-partitions)] |
| 134 | + (into [] |
| 135 | + (comp (map-indexed (fn [i x] |
| 136 | + [(long (math/floor (/ i partition-size))) x])) |
| 137 | + (partition-by first) |
| 138 | + (map (fn [partition] |
| 139 | + (map second partition)))) |
| 140 | + xs))) |
| 141 | + |
| 142 | +(defn- partition-tests [tests {num-partitions :partition/total, partition-index :partition/index, :as _options}] |
| 143 | + (if (or num-partitions partition-index) |
| 144 | + (do |
| 145 | + (assert (and num-partitions partition-index) |
| 146 | + ":partition/total and :partition/index must be set together") |
| 147 | + (assert (pos-int? num-partitions) |
| 148 | + "Invalid :partition/total - must be a positive integer") |
| 149 | + (assert (<= num-partitions (count tests)) |
| 150 | + "Invalid :partition/total - cannot have more partitions than number of tests") |
| 151 | + (assert (int? partition-index) |
| 152 | + "Invalid :partition/index - must be an integer") |
| 153 | + (assert (<= 0 partition-index (dec num-partitions)) |
| 154 | + (format "Invalid :partition/index - must be between 0 and %d" (dec num-partitions))) |
| 155 | + (let [partitions (partition-all-into-n-partitions num-partitions tests) |
| 156 | + partition (nth partitions partition-index)] |
| 157 | + (printf "Running tests in partition %d of %d (%d tests of %d)...\n" |
| 158 | + (inc partition-index) |
| 159 | + num-partitions |
| 160 | + (count partition) |
| 161 | + (count tests)) |
| 162 | + partition)) |
| 163 | + tests)) |
| 164 | + |
123 | 165 | (defn find-tests-with-options
|
124 | 166 | "Find tests using the options map as passed to `clojure -X`."
|
125 | 167 | [{:keys [only], :as options}]
|
126 | 168 | (println "Running tests with options" (pr-str options))
|
127 | 169 | (when only
|
128 | 170 | (println "Running tests in" (pr-str only)))
|
129 | 171 | (let [start-time-ms (System/currentTimeMillis)
|
130 |
| - tests (find-tests only options)] |
| 172 | + tests (-> (find-tests only options) |
| 173 | + (partition-tests options))] |
131 | 174 | (printf "Finding tests took %s.\n" (u/format-milliseconds (- (System/currentTimeMillis) start-time-ms)))
|
132 | 175 | (println "Running" (count tests) "tests")
|
133 | 176 | tests))
|
|
0 commit comments