I have seen many clojure projects that disable integration tests by default by adding this setting to project.clj
:
:test-selectors {:default (complement :integration)
:integration :integration}
But, if a namespace contains only integration tests, the fixtures in it still run when I run lein test
!
For example if I run lein new app test
and make the contents of core_test.clj
this:
(defn fixture [f]
(println "Expensive setup fixture is running")
(f))
(use-fixtures :once fixture)
(deftest ^:integration a-test
(println "integration test running"))
Then when I run lein test
I see the fixture running even though no tests are run.
What is the correct way to handle this in clojure?
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.