Writing good tests is something that is important in virtually all software projects. In this blog we’ll use Midje and Leiningen for integration testing. Midje is a test framework for Clojure whose purpose is to provide a way to write readable tests (facts) easily. For example:
; Test1
(fact "Fact description"
[1 2 3 4] => (just [odd? even? odd? even?]))
Leiningen is the de facto build tool for Clojure and Midje provides a plugin that allows you to run all Midje tests using:
lein midje
Tag facts as integration tests
While this works great you probably want to distinguish between unit tests (fast and small scope) and integration tests (slower and larger scope). Midje provides a to do this by using filters. For example we can use the :it
keyword to tag our facts as integration tests:
; Test2
(fact "A slow integration test" :it
(slow-network-stuff) => 42)
Running the integration tests from Leiningen now looks like this:
lein midje :filters it
This will run Test2
but not Test1
. To run only the unit tests and not the integration tests we can do:
lein midje :filters -it
Add integration test source folder
By default all tests in Leiningen are located in the test
folder. Placing both unit tests and integration tests in the same folder makes it hard to distingiush between them. I prefer to have a seperate folder for unit and integration tests. It’s easy to do this in Leiningen once you know how it’s done. All you need to do is to specify the :test-paths
key in Leiningen’s project.clj
:
...
:test-paths ["test" "itest"]
...
Here we add the itest
folder to the test classpath. Thus we can place all our integration tests in this folder and have them separated from our unit tests.
Aliases
In order to write less and make it a bit easier to remember how to apply Midje filters we can make aliases for running our tasks in Leiningen. First we’ll create an alias for running the integration tests in our project.clj
:
:aliases {"itest" ["midje" ":filters" "it"]}
This allows us to run the integration tests from Leiningen using:
lein itest
Likewise we can add an alias (utest
) for running only the unit tests:
:aliases {"itest" ["midje" ":filters" "it"]
"utest" ["midje" ":filters" "-it"]}
If we’re only using Midje in the project we could replace the standard test
task with Midje:
:aliases {"itest" ["midje" ":filters" "it"]
"utest" ["midje" ":filters" "-it"]
"test" ["midje"]}
Running lein test
now will execute all Midje tests (both unit and integration tests).
Summary
Both Midje and Leiningen are flexible enough to allow us to configure our test environment as we find fit. A full example of a project.clj
file configured with the above settings is shown here:
(defproject test-project "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.6.0"]]
:min-lein-version "2.0.0"
:profiles {:dev
{
:dependencies [[midje "1.6.3"]]
:plugins [[lein-midje "3.1.3"]]
}
}
:test-paths ["test" "itest"]
:aliases {"itest" ["midje" ":filters" "it"]
"test" ["midje"]
"utest" ["midje" ":filters" "-it"]})
Happy testing!
Hey Johan,
Great post! I’ve been trying to find a simple and easy way of running integration tests and this seems to be it!
One question though, have you tried using midje with fixtures?
Thanks. Unfortunately I haven’t used midje fixtures.
Ah not to worry! Thanks again :)
This was just the article I was looking for – thanks Johan.