lambdaisland / kaocha

Full featured next gen Clojure test runner
https://cljdoc.org/d/lambdaisland/kaocha/1.0.861/doc/1-introduction
Eclipse Public License 1.0
796 stars 82 forks source link

doctests / examples #365

Open plexus opened 1 year ago

plexus commented 1 year ago

See an earlier draft pitch here (not all of it still matches my thinking, but linking for reference).

https://nextjournal.com/lambdaisland/pitch-kaocha-doctests

Some languages have "doctests", the ability to encode examples in docstrings, and have them verified by the test runner. This relies on agreeing on some syntax, e.g. elixer recognizes >>> at the start of a docstring line as code, and the following line(s) as the result, so it looks like what you would see in a REPL session.

e.g. in clojure you could imagine something like this

(defn my-sort 
  "Sorts a sequence.

  > (my-sort [4 1 3])
  ;;=> (1 3 4)
  "
  [s]
  (sort s))

Now while I think there's a lot of merit to this because it means any existing doc tools will also render these examples (which is part of the point), it's still really tedious to edit clojure inside strings. I'd much prefer to see something like this.

(defn my-sort
  {:examples '{(sort [4 3 5]) [3 4 5]
               (sort nil) []}}
  [s]
  (sort s))

In fact I've written code like this in the past, with the idea that it's already helpful just as inline documentation, and with the idea that it would be trivial to have kaocha run these as tests, I just never got around to the last part.

That said if we go down the metadata route, than I want to see a parallel effort to get this same syntax recognized in other tools, the main ones would be

These are also not mutually exclusive, I can see us implementing both.

alysbrooks commented 1 year ago

I read an interesting proposal by Zach Oakes from a few years ago about interactive examples: https://gist.github.com/oakes/8db57ac808bf6ec144d627fd83a89da3. Adding interactivity is too much for the first version, but I think we should try to choose a syntax that will support tat use case.

alysbrooks commented 1 year ago

Codox actually has interactive examples that have no expected output: https://github.com/viebel/codox-klipse-theme. Unfortunately, I'm not sure we could use their format easily.

More prior art:

The common syntax seems to use "=>" to indicate executed Clojure, with the return value appearing on the next line.

alysbrooks commented 1 year ago

This syntax might be too heavyweight, but we could also introduce a with-doctests macro:


(with-doctests
  (defn my-sort
    [s]
    (sort s))

  (sort [4 3 5]) [3 4 5]
  (sort nil) [])
alysbrooks commented 1 year ago

rich-comment-tests takes a slightly different approach: https://github.com/matthewdowney/rich-comment-tests. It also uses => but the example has them on the same line.

They already have clojure.test integration, so it may work with Kaocha already. Here's their example:


(ns some-test-ns
  (:require [clojure.test :refer :all]
    [com.mjdowney.rich-comment-tests.test-runner :as test-runner]))

(deftest rct-tests
  (test-runner/run-tests-in-file-tree! :dirs #{"src"}))
alysbrooks commented 1 year ago

Hyperfiddle also has their own version (which apparently inspired rich-comment-tests): https://github.com/hyperfiddle/rcf

plexus commented 1 year ago

First implementation here: https://github.com/lambdaisland/kaocha-doctest