Skip to content

Commit

Permalink
Switch from :test metadata to :lazytest/test
Browse files Browse the repository at this point in the history
  • Loading branch information
NoahTheDuke committed Nov 14, 2024
1 parent 068b529 commit 5828b28
Show file tree
Hide file tree
Showing 7 changed files with 38 additions and 29 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

is rewritten as `(expect (int? (+ 1 1)))`.

- Switch from `:test` metadata to `:lazytest/test` metadata. It's longer, but it no longer clashes with `clojure.test`'s internals so you can run lazytest over `clojure.test` tests without them being marked as passing tests. (See [#4](https://github.com/NoahTheDuke/lazytest/issues/4).)

## 1.3.0

Released `2024-10-21`.
Expand Down
33 changes: 19 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,21 +195,22 @@ There are a number of experimental namespaces that define other aliases, with di

### Var Metadata

In addition to finding the tests defined with `defdescribe`, Lazytest also checks all vars for `:test` metadata. If the `: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. `:test` functions are given the doc string ``"`:test` 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:

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

Expand All @@ -218,7 +219,7 @@ How they're printed:
```
lazytest.readme-test
#'lazytest.readme-test/fn-example
√ `:test` metadata
√ `:lazytest/test` metadata
#'lazytest.readme-test/test-case-example
√ test case example docstring
#'lazytest.readme-test/describe-example
Expand All @@ -233,13 +234,17 @@ These can get unweildy if multiple test cases are included before a given implem
(defn post-attr-example
([a b]
(+ a b))
{: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)))))})
{: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.
## Partitioning Individual Tests and Suites

All of the test suite and test case macros (`defdescribe`, `describe`, `it`, `expect-it`) take a metadata map after the docstring. Adding `:focus true` to this map will cause *only* that test/suite to be run. Removing it will return to the normal behavior (run all tests).
Expand Down Expand Up @@ -515,8 +520,8 @@ This is inspired by [Mocha](https://mochajs.org)'s excellent documentation.
5. Lazytest gathers all test vars from the required namespaces. It checks each var in each namespace against the following list of questions.
1. Is the var defined with `defdescribe`? Call the `defdescribe`-constructed function and use it.
2. Does the var point to a `suite`? Use it.
3. Does the var have `:test` metadata that is either a suite (`describe`) or a test case (`it`)? Create a new suite with `describe` and set the `:test` metadata as a child.
4. Does the var have `:test` metadata that is a function? Create a new suite with `describe`, create a new test case with `it`, and then set the docstring for the test case to `:test metadata`, and the body to calling the `:test` metadata function.
3. Does the var have `:lazytest/test` metadata that is either a suite (`describe`) or a test case (`it`)? Create a new suite with `describe` and set the `:lazytest/test` metadata as a child.
4. Does the var have `:lazytest/test` metadata that is a function? Create a new suite with `describe`, create a new test case with `it`, and then set the docstring for the test case to `:lazytest/test metadata`, and the body to calling the `:lazytest/test` metadata function.
6. Lazytest groups each namespace into a `:lazytest/ns` suite, and then groups all of the namespace suites into a `:lazytest/run` suite.
7. Lazytest does a depth-first walk of the run suite, filtering nses by `--namespace`, vars by `--var`, and all suites and test cases by `--include` or `--exclude` (with `:focus` being automatically included). These are prioritized as such:
1. `--namespace` narrows all namespaces to those that exactly match. The namespaces of `--var` vars are included as well. If `--namespace` is not provided, all namespaces are selected.
Expand Down
14 changes: 8 additions & 6 deletions corpus/find_tests/examples.clj
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,21 @@
[lazytest.core :refer [describe expect it]]))

(defn test-fn
{:test #(expect (= 0 (test-fn 1)))}
{:lazytest/test #(expect (= 0 (test-fn 1)))}
[a]
(+ a a))

(defn test-test-case
{:test (it "test case example"
(expect (= 1 (test-test-case 1))))}
{:lazytest/test
(it "test case example"
(expect (= 1 (test-test-case 1))))}
[a]
(+ a a))

(defn test-describe
{:test (describe "top level"
(it "test-describe example" (expect (= 1 (test-describe 1))))
(it "test-describe example two" (expect (= 0 (test-describe 1)))))}
{:lazytest/test
(describe "top level"
(it "test-describe example" (expect (= 1 (test-describe 1))))
(it "test-describe example two" (expect (= 0 (test-describe 1)))))}
[a]
(+ a a))
2 changes: 1 addition & 1 deletion src/clojure/lazytest/cli.clj
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,6 @@
(:version options) {:exit-message "lazytest 0.0" :ok true}
errors (print-errors errors)
:else (-> options
(update :dir (comp vec concat) arguments)
(update :dir (comp not-empty vec concat) arguments)
(update :output prepare-output)
(update :delay #(or % 500))))))
10 changes: 5 additions & 5 deletions src/clojure/lazytest/find.clj
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,24 @@
(when (bound? the-var)
(let [value (var-get the-var)
m (meta the-var)
test-metadata (:test m)]
test-metadata (:lazytest/test m)]
(cond
;; (defdescribe example ...)
(= :lazytest/var (:type m))
(set-var (value) the-var)
;; (def example (describe ...))
(suite? value)
(set-var value the-var)
;; (defn example {:test (describe ...)})
;; (defn example {:test (it ...)})
;; (defn example {:lazytest/test (describe ...)})
;; (defn example {:lazytest/test (it ...)})
(or (suite? test-metadata)
(test-case? test-metadata))
(let [new-test (describe the-var)]
(set-var (update new-test :children conj test-metadata) the-var))
;; (defn example {:test #(expect ...)})
;; (defn example {:lazytest/test #(expect ...)})
(fn? test-metadata)
(set-var (describe the-var
(-> (it "`:test` metadata" (test-metadata))
(-> (it "`:lazytest/test` metadata" (test-metadata))
(merge (select-keys m [:line :column]))))
the-var)))))

Expand Down
2 changes: 1 addition & 1 deletion src/clojure/lazytest/runner.clj
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@
(run-tests nil config)))

(defn run-test-var
"Run test var. Looks for a suite as the var's value or in `:test` metadata. Applies filters in config."
"Run test var. Looks for a suite as the var's value or in `:lazytest/test` metadata. Applies filters in config."
([v] (run-test-var v (->config nil)))
([v config]
(assert (var? v) "Must be a var")
Expand Down
4 changes: 2 additions & 2 deletions test/clojure/lazytest/find_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
:doc (resolve 'find-tests.examples/test-fn)
:children
[{:type :fail
:doc "`:test` metadata"
:doc "`:lazytest/test` metadata"
:thrown (ex-info "Expectation failed"
{:type 'lazytest.ExpectationFailed
:expected '(= 0 (test-fn 1))})}]}
Expand Down Expand Up @@ -70,7 +70,7 @@
"\n"
[" find-tests.examples"
" #'find-tests.examples/test-fn"
" × `:test` metadata FAIL"
" × `:lazytest/test` metadata FAIL"
" #'find-tests.examples/test-test-case"
" × test case example FAIL"
" #'find-tests.examples/test-describe"
Expand Down

0 comments on commit 5828b28

Please sign in to comment.