Liking cljdoc? Tell your friends :D

Writing tests with Lazytest

The primary api is found in lazytest.core namespace. It mimics the behavior-driven testing style popularized by libraries such as RSpec and Mocha.

Define tests with defdescribe, group test suites and test cases together into a suite with describe, and define test cases with it. describe can be nested. defdescribe's docstring is optional, describe and it's docstrings are not.

(require '[lazytest.core :refer [defdescribe describe expect it]])

(defdescribe +-test "with integers"
  (it "computes the sum of 1 and 2"
    (expect (= 3 (+ 1 2))))
  (it "computes the sum of 3 and 4"
    (assert (= 7 (+ 3 4))))
  (describe "associative property"
    (it "works in both directions"
      (expect (= 3 (+ 1 2)))
      (expect (= 3 (+ 2 1))))))

The expect macro is like assert but carries more information about the failure, such as the given form, the returned value, and the location of the call. It throws an exception if the expression does not evaluate to logical true.

If an it runs to completion without throwing, the test case is considered to have passed.

The describe macro creates a test suite, a map containing :children (among other things) which are nested suites or test cases (created with it). It can be passed to other functions or tests, it can be updated with other code, it can be removed from parent suites. Unlike clojure.test/testing, it is not merely setting a context string that is used to generate helpful error messages.

important

This is maybe the greatest divergence from clojure.test, so it's important to emphasize this. Test cases (the objects created by it) are not run when a test function (defdescribe) is called or a test suite (describe) is evaluated. Each of these returns an object (a map, to be specific), and the lazytest.runner machinery traverses them and calls the test case function body only when appropriate. This means that you cannot write normal clojure code outside of it blocks, as it will work slightly differently than anticipated.

For more details and ways to work around this, please read the section on Setup and Teardown.

Aliases

To help write meaningful tests, a couple aliases have been defined for those who prefer different vocabulary:

These can be used interchangeably:

(require '[lazytest.core :refer [context specify should]])

(defdescribe context-test
  (context "with integers"
    (specify "that sums work"
      (should (= 7 (+ 3 4)) "follows basic math")
      (expect (not= 7 (+ 1 1))))))

There are a number of experimental namespaces that define other aliases, with distinct behavior, if the base set of vars don't fit your needs:

Var Metadata

In addition to finding the tests defined with defdescribe, Lazytest also checks all vars for :lazytest/test metadata. If the :lazytest/test metadata is a function, a test case, or a test suite, it's treated as a top-level defdescribe for the associated var and executed just like other tests. :lazytest/test functions are given the doc string "`:lazytest/test` metadata".

How to write them:

(defn fn-example
  {:lazytest/test #(expect (= 1 1))}
  [])
(defn test-case-example
  {:lazytest/test (it "test case example docstring" (expect (= 1 1)))}
  [])
(defn describe-example
  {:lazytest/test
    (describe "top level docstring"
      (it "first test case" (expect (= 1 1)))
      (it "second test case" (expect (= 1 1))))}
  [])

How they're printed:

  lazytest.readme-test
    #'lazytest.readme-test/fn-example
      √ `:lazytest/test` metadata
    #'lazytest.readme-test/test-case-example
      √ test case example docstring
    #'lazytest.readme-test/describe-example
      top level docstring
        √ first test case
        √ second test case

These can get unweildy if multiple test cases are included before a given implementation, so I recommend either moving them to a dedicated test file or moving the attr-map to the end of the function definition:

(defn post-attr-example
  ([a b]
   (+ a b))
  {:lazytest/test
   (describe "Should be simple addition"
     (it "handles ints"
       (expect (= 2 (post-attr-example 1 1))))
     (it "handles floats"
       (expect (= 2.0 (post-attr-example 1.0 1.0)))))})

note

Lazytest previously used :test metadata, but because clojure.test relies on that, it impeded having both clojure.test and Lazytest tests in a given codebase.

Can you improve this documentation?Edit on GitHub

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close