TDD Workflow in Clojure using Emacs with CIDER
Sign up for weekly Clojure tips, software design, and a Clojure coding challenge.
Summary: TDD is about fast feedback. CIDER tightens the feedback loop with quick commands for running tests and a powerful test reporting system.
I've always been into flow. One of the key aspects of flow is a short feedback loop. Test Driven Development (TDD) is partially based on flow, too. You write a new test, then you write code to satisfy the test, then you refactor. You cycle quickly with very small steps. Great for flow!
Now, I'm not going to be a pedant in this post about what is and what is not TDD. Sometimes I like to adhere to a strict discipline of TDD. And sometimes I like to code fast and loose. But as a working definition, for the purposes of this article, I'll define TDD as writing code and tests incrementally, and running the tests fairly often. The last thing you want is to have to wait for those tests to run.
ask me any time for help (eric at lispcast dot com)
if you run into trouble.
What you need to know
First, you'll need CIDER connected to the REPL (usually just
Besides the basic commands for switching buffers (
C-c b), I use just
one command a ton while I'm TDD'ing:
C-c C-t n(That's Control-c Control-t n.) While you're in a buffer, it will run the tests for that buffer. It could be that you're in production code, in which case it will try to find the corresponding test namespace and run tests there.
That will give you just the feedback you need: a green status report in the status bar if everything passes. And a new buffer with a failure and error report if it's not passing. You can do some cool stuff in that buffer, like jumping to the test definition, rerunning individual tests, and seeing diffs of actual vs. expected output. Look here for a quick reference to the available key bindings.
But mostly I'm editing code, compiling it (with
C-c C-k), and running
the tests (
C-c C-t n) to make sure they pass now. Unlike with running
lein test at the command line, this command only runs the tests for
that specific namespace. This is usually what you want while you're
editing code in the namespace. After you're done, you'll want to rerun
all of the tests in a fresh JVM at the command line.
Getting a productive workflow set up is really important. It's hard on our nerves to be waiting through long feedback cycles. CIDER tightens those loops down to human scale so we can focus on the work of making the world better.
If you'd like to learn more about testing in Clojure, including how to
write tests so that they work seamlessly with Leiningen and CIDER, I
have to recommend my LispCast Intro to
It covers the most important and fundamental concepts and skills for
testing in Clojure. You should not miss the free