@@ -3412,6 +3412,105 @@ with `deftest` and name them `something-test`.
34123412(deftest something ...)
34133413----
34143414
3415+ === Use `testing` Blocks for Context [[use-testing-blocks]]
3416+
3417+ Group related assertions under `testing` to provide context in
3418+ failure output. This makes it clear which scenario failed without
3419+ having to read the assertion itself.
3420+
3421+ [source,clojure]
3422+ ----
3423+ ;; good
3424+ (deftest user-validation-test
3425+ (testing "rejects blank names"
3426+ (is (not (valid? {:name ""}))))
3427+ (testing "accepts valid names"
3428+ (is (valid? {:name "Bruce"}))))
3429+
3430+ ;; bad - no context when an assertion fails
3431+ (deftest user-validation-test
3432+ (is (not (valid? {:name ""})))
3433+ (is (valid? {:name "Bruce"})))
3434+ ----
3435+
3436+ === Prefer Informative Assertion Messages [[informative-assertion-messages]]
3437+
3438+ Add messages to `is` when the assertion alone doesn't explain the
3439+ failure.
3440+
3441+ [source,clojure]
3442+ ----
3443+ ;; good - the failure message explains what went wrong
3444+ (is (= 200 (:status response)) "Expected HTTP 200 for valid input")
3445+
3446+ ;; ok - obvious assertions don't need a message
3447+ (is (true? (even? 4)))
3448+ ----
3449+
3450+ === Use `are` for Tabular Tests [[use-are-for-tabular-tests]]
3451+
3452+ When testing the same logic with many inputs, prefer `are` over
3453+ repetitive `is` forms.
3454+
3455+ [source,clojure]
3456+ ----
3457+ ;; good
3458+ (deftest palindrome?-test
3459+ (are [s expected] (= expected (palindrome? s))
3460+ "racecar" true
3461+ "hello" false
3462+ "madam" true
3463+ "" true))
3464+
3465+ ;; bad - repetitive
3466+ (deftest palindrome?-test
3467+ (is (true? (palindrome? "racecar")))
3468+ (is (false? (palindrome? "hello")))
3469+ (is (true? (palindrome? "madam")))
3470+ (is (true? (palindrome? ""))))
3471+ ----
3472+
3473+ === Test One Concept per `deftest` [[one-concept-per-deftest]]
3474+
3475+ Each `deftest` should cover one logical behavior. Use `testing`
3476+ blocks for sub-cases rather than separate `deftest` forms for every
3477+ edge case.
3478+
3479+ === Use `with-redefs` Sparingly [[use-with-redefs-sparingly]]
3480+
3481+ Use `with-redefs` only for external boundaries (HTTP, database,
3482+ clock). Prefer designing functions to take dependencies as arguments
3483+ instead.
3484+
3485+ [source,clojure]
3486+ ----
3487+ ;; good - inject the dependency
3488+ (defn fetch-users [http-get]
3489+ (http-get "/api/users"))
3490+
3491+ (deftest fetch-users-test
3492+ (is (= [{:name "Bruce"}]
3493+ (fetch-users (constantly [{:name "Bruce"}])))))
3494+
3495+ ;; ok for integration-level tests
3496+ (deftest fetch-users-integration-test
3497+ (with-redefs [http/get (constantly {:body [{:name "Bruce"}]})]
3498+ (is (= [{:name "Bruce"}] (fetch-users)))))
3499+ ----
3500+
3501+ === Test Expected Exceptions [[test-expected-exceptions]]
3502+
3503+ Use `thrown?` and `thrown-with-msg?` to assert that code raises the
3504+ expected exception.
3505+
3506+ [source,clojure]
3507+ ----
3508+ ;; good
3509+ (deftest division-test
3510+ (is (thrown? ArithmeticException (/ 1 0)))
3511+ (is (thrown-with-msg? ExceptionInfo #"Invalid" (validate! nil))))
3512+ ----
3513+
34153514== Library Organization
34163515
34173516=== Library Coordinates [[lib-coordinates]]
0 commit comments