One way to accomplish not running the expensive computation is to take advantage of the fact that even though the :once
fixtures will run regardless of whether there are tests to run in the ns or not, the :each
fixtures will only run on each actually-running test.
Instead of doing the actual computation (or acquiring resources like a db connection, or doing whatever side-effects) in the :once
fixture, we only do it in the first (we want to do it only once!) :each
fixture, for example doing as following:
(def run-fixture? (atom true))
(defn enable-fixture [f]
(println "enabling expensive fixture...")
(try
(f)
(finally (reset! run-fixture? true))))
(defn expensive-fixture [f]
(if @run-fixture?
(do
(println "doing expensive computation and acquiring resources...")
(reset! run-fixture? false))
(println "yay, expensive thing is done!"))
(f))
(use-fixtures :once enable-fixture)
(use-fixtures :each expensive-fixture)
(deftest ^:integration integration-test
(println "first integration test"))
(deftest ^:integration second-integration-test
(println "second integration test"))
The output of lein test
will be as following (notice how the enable-fixture
has run but not the expensive expensive-fixture
):
› lein test
lein test fixture.core-test
enabling expensive fixture...
Ran 0 tests containing 0 assertions.
0 failures, 0 errors.
When running lein test :integration
, the expensive-fixture
will run exactly once:
› lein test :integration
lein test fixture.core-test
enabling expensive fixture...
doing expensive computation and acquiring resources...
first integration test
yay, expensive thing is done!
second integration test
Ran 2 tests containing 0 assertions.
0 failures, 0 errors.