Explore how to effectively automate test execution in Clojure projects using Leiningen and Boot, including configuration, customization, and integration with CI pipelines.
Automated testing is a cornerstone of modern software development, ensuring that code changes do not introduce regressions and that the software behaves as expected. In the Clojure ecosystem, Leiningen and Boot are two primary build tools that facilitate automated test execution. This section delves into how to leverage these tools to run tests efficiently, configure test paths, include or exclude tests based on metadata, and integrate test execution into continuous integration (CI) pipelines.
Leiningen is a popular build automation tool for Clojure that simplifies project management, including running tests. The lein test
command is the primary way to execute tests in a Leiningen-managed project.
project.clj
By default, Leiningen expects test files to reside in the test
directory of your project. However, you can customize this behavior by specifying test paths in your project.clj
file. Here’s an example configuration:
(defproject my-clojure-project "0.1.0-SNAPSHOT"
:description "A sample Clojure project"
:dependencies [[org.clojure/clojure "1.10.3"]]
:test-paths ["test" "custom-test-dir"])
In this configuration, Leiningen will look for test files in both the test
and custom-test-dir
directories.
lein test
To execute tests, simply run the following command in your terminal:
lein test
This command will automatically discover and run all test namespaces in the specified test paths. Leiningen uses the clojure.test
framework by default, which is included in the Clojure standard library.
Leiningen allows you to include or exclude tests based on metadata. This is useful for running a subset of tests, such as integration tests or tests marked as slow. You can add metadata to your tests using the :test
metadata key:
(ns my-clojure-project.core-test
(:require [clojure.test :refer :all]))
(deftest ^:integration test-integration-feature
(is (= 1 1)))
(deftest ^:unit test-unit-feature
(is (= 2 2)))
To run only integration tests, use the :only
option with lein test
:
lein test :only :integration
Conversely, to exclude integration tests, use the :exclude
option:
lein test :exclude :integration
Boot is another powerful build tool for Clojure that offers a flexible pipeline architecture. Running tests in Boot involves using the test
task, which can be customized to suit your needs.
test
TaskTo run tests in a Boot project, you first need to include the boot-test
dependency in your build.boot
file:
(set-env!
:dependencies '[[org.clojure/clojure "1.10.3"]
[adzerk/boot-test "2.0.0"]])
(require '[adzerk.boot-test :refer [test]])
(deftask run-tests []
(comp (test)))
With this setup, you can execute tests by running the following command:
boot run-tests
Boot allows you to customize test runners by specifying options in the test
task. For example, you can run tests in parallel or specify a custom test reporter:
(deftask run-tests []
(comp (test :parallel true :reporter :junit)))
This configuration runs tests in parallel and uses the JUnit reporter for output.
Automated test execution is a critical component of continuous integration (CI) pipelines. Both Leiningen and Boot can be integrated into CI systems like Jenkins, Travis CI, and GitHub Actions.
Here’s a simple example of a GitHub Actions workflow that runs tests using Leiningen:
name: Clojure CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 11
uses: actions/setup-java@v1
with:
java-version: '11'
- name: Install Leiningen
run: |
curl https://raw.githubusercontent.com/technomancy/leiningen/stable/bin/lein > ~/bin/lein
chmod +x ~/bin/lein
- name: Run tests
run: lein test
This workflow triggers on every push and pull request, ensuring that tests are run automatically.
To integrate Boot with Jenkins, you can create a Jenkins pipeline script that includes a step to run Boot tests:
pipeline {
agent any
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Build and Test') {
steps {
sh 'boot run-tests'
}
}
}
}
Continuous testing provides several advantages:
Automated test execution is an essential practice for maintaining robust and reliable Clojure applications. By leveraging Leiningen and Boot, developers can configure and run tests efficiently, integrate testing into CI pipelines, and enjoy the benefits of continuous testing. Whether you are working on a small project or a large enterprise application, these tools provide the flexibility and power needed to ensure your code meets the highest quality standards.