Testing with clojure.test

Other tools: Kaocha (feature-rich test runner, watch mode, plugins), matcher-combinators (expressive assertions for nested data), eftest (parallel runner), and etaoin (browser automation).

;; test/myapp/orders_test.clj
(ns myapp.orders-test
  (:require [clojure.test :refer [deftest is are testing use-fixtures]]
            [myapp.orders :as orders]))

(deftest total-test
  (testing "empty order"
    (is (= 0 (orders/total []))))
  (testing "single item"
    (is (= 10 (orders/total [{:price 10 :qty 1}]))))
  (testing "throws on invalid data"
    (is (thrown? IllegalArgumentException (orders/total nil)))
    (is (thrown-with-msg? clojure.lang.ExceptionInfo #"Invalid" (orders/validate! {})))))

(deftest arithmetic
  (are [x y expected] (= expected (+ x y))       ; table-driven tests
    1 2 3
    0 0 0
    -1 1 0))

;; Fixtures: setup/teardown around each test or once per namespace
(defn with-db [f]
  (let [db (start-test-db)]
    (try (binding [*db* db] (f))
         (finally (stop-test-db db)))))
(use-fixtures :each with-db)

;; Mocking with with-redefs
(deftest fetch-test
  (with-redefs [orders/fetch-remote (fn [_] {:status :ok})]
    (is (= :ok (:status (orders/sync! 1))))))
clj -X:test                              # cognitect test-runner
lein test
bb test                                  # with Babashka tasks