This is a weblog about computing, culture et cetera, by Miikka Koskinen. Read more.
Ripping seams is easy when you use the right tool.
David R. MacIver has a list of some things that might help you make better software. Some of the things, like continuous integration, require technical tooling in addition to adopting the practices.
If you agree with David’s list – and I do - this raises a question: does your technical stack provide the tooling needed for implementing David’s suggestions? In my case, do these tools exist for Clojure and ClojureScript? Let’s find out.
Continuous integration. No problems here: CI servers are mostly language-agnostic. If you want a hosted solution, there’s e.g. Travis and Circle, and if you prefer running your own, Jenkins is always there.
Local automated tests. For Clojure, things are okay. Test runners are not perfect, but there’s a reasonable workflow for running single tests in common editors like Emacs and Cursive, and running the whole test suite obviously works. For ClojureScript, there’s a workable setup for the whole test suite. In theory, the same editor workflow should work for ClojureScript, but in practice I’ve always encountered problems with the ClojureScript REPL.
Code coverage. For Clojure, there’s cloverage, although I’ve had some trouble with making it work with all the projects. As far as I know, there’s nothing for ClojureScript yet. Maybe something could be whipped up with Istanbuland remap-istanbul?
Property-based testing. There’s test.check, which David ranks as very good. clojure.spec’s generator support makes it even nicer. It works with both Clojure and ClojureScript.
Static analysis. Cursive does some in-editor analysis with both Clojure and ClojureScript. For Clojure, there’s Eastwood, which does not work with every project, but it is nice when it works. There’s also kibit, which is less useful, but also works with ClojureScript.
Auto formatting and style checking. At least both Cursive and Emacs have support for reformatting Clojure(Script) code. cljfmt can both check and format your code and lein-bikeshed checks some things as well. They’re not quite as advanced as something like ESLint, though.
Overall, I’d rate the situation as okay but not amazing. If you look at David’s list, having the right processes and the right culture will have much bigger impact than having good tools. On the other hand, changing any processes involving tools is easier when the tools actually work.
In the previous post I mentioned that you can use Karma to run ClojureScript tests. The easiest way to do it is to use doo or boot-cljs-test. Sometimes you need more advanced configuration and it’s best to use Karma directly. I’ve set up a GitHub repository that shows how to do it.
It’s actually pretty straightforward, but that was not obvious to me before I tried to do it.
How do you run your Clojure unit tests? Does it make you happy?
When working on new code, I rely on CIDER’s clojure.test support. It allows you to run all tests in a namespace and then re-run the failed ones after you’ve made changes. This is good, because it makes the feedback loop tight: write code, send it to the REPL, run the tests, repeat. Cursive supports a similar workflow.
When I want to run the full test suite from the command-line, for example in a CI job, none of the available test runners makes me fully happy. For large test suites - especially the ones with integration tests - I’d like to have the following:
- Output catching. If a test prints something to stdout, it should be shown only if the test fails. There’s no point in wading through thousands of lines of logs generated by succesful tests to find that one actual exception.
- Test tagging. Many test runners allow you to filter tests by name. I’d like to filter them by custom tags. For example, I’d like to say “run all the tests except those tagged with
Here are some less essential but still nice to have features:
- JUnit output in addition to the normal output. CI tools like Jenkins or Circle know how to create nice reports from JUnit output. The reports are helpful for making sense of large test suites. clojure.test knows how to generate JUnit, but it can only do it instead of the normal output. When debugging test failures, I prefer the usual logs to the nice reports.
- Reporting the slowest tests. This is not something I care about all the time, but it’s handy when you wonder why the full test suite takes 45 minutes to run.
I’ve seen or implemented all of the above in custom test runners, but none of the open-source runners –
lein test, boot-test, eftest, boot-alt-test, … – offers everything in a coherent package. Basically what I want is pytest for Clojure. Supporting ClojureScript would be great, too, although you can already use Karma with karma-cljs-test.
Since I know what I want, I should just go ahead and implement this, right? Right. I wanted to try something new and first write about this to see if anyone else cares. Does anyone else miss these features?
For more posts, see archive.