Search

Dark theme | Light theme

May 19, 2024

Clojure Goodness: Combine Multiple Test Cases With are

The clojure.test namespace has the are macro that allows us to combine multiple test cases for the code we want to test, without having to write multiple assertions. We can provide multiple values for a function we want to test together with the expected values. Then then macro will expand this to multiple expressions with the is macro where the real assertion happens. Besides providing the data we must also provide the predicate where we assert our code under test. There is a downside of the are macro and that is that in case of assertion failures the line numbers in the error message could be off.

The first argument of the are macro is a vector with symbols that represent the names of the variables we want to use in the predicate. The second argument is the predicate where we write our assertion for the code under test. The remaining arguments are values for the symbols in the first argument. We can provide multiple sets of values for the symbols in the first argument, and the are macro will use this when the macro is expanded into multiple expressions.

In the next example we use the are macro to test the full-name function.

(ns mrhaki.test
  (:require [clojure.test :refer [deftest are]]
            [clojure.string :as str]))

;; Function we want to test.
(defn is-palidrome?
  [s]
  (= s (str/reverse s)))

(deftest palidrome
  (are
   ;; Vector with symbol used in test expression
   [s]
   ;; Test expression where we test the is-palidrome? function
   (true? (is-palidrome? s))
    ;; Data for the input symbol s
    "radar"
    "kayak"
    "racecar"
    "madam"
    "refer"
    "step on no pets"))

In the following example we use a test expression where we also use an expected value that is provided with the input data:

(ns mrhaki.test
  (:require [clojure.test :refer [deftest are]]))

;; Function we want to test.
(defn full-name
  "Returns a full name"
  [first-name last-name]
  (str first-name " " last-name))

(deftest sample
  (are
   [first-name last-name result]
   (= (full-name first-name last-name) result)
    "Fat" "Tony" "Fat Tony"
    "Krusty" "the Clown" "Krusty the Clown"))

Written with Clojure 1.11.3.