hey @karol.wojcik i saw that you wrote a custom reporter for lazytest. you're the first one from what i can tell, and i'm interested in hearing your experience working with lazytest.
you had to do some naughtiness to make it work (redef'ing try-test-case to capture output), which is an area we could clean up
Craftsmanship is dead. It was not even me who did this part. It was mix of Claude/GPT/GLM and friends.
😅
Btw, lazytest is awesome. Boost of productivity is enormous compared to Clojure.test
i'm so glad you think so!
final question for y'all before i merge this thing: as i have it written, hooks are expected to be functions that take the config object and a map of some kind (a suite or a test-case or the config itself). i'm assoc'ing the ::hook-type onto the target map, and my built-in dispatch function expects that. however, this means that the :cli-opts method (which collects custom entries for tools.cli) needs to pass in a map, not a vector, and the output is expected to be a map as well, which leads to messiness of (cli-opts [config opts] (update opts :new conj [...] [...])). that's ugly, and if i can think of the write way to go about this, can be avoided entirely
ideas:
1. move the dispatch keyword onto config, which will always be a map. this "hides" the dispatch value from the target object and allows for passing in non-map objects (such as a vector of cli options).
2. have a third arg, the dispatch value. the arg-list becomes [dispatch-kw config target] , and users would be expected to write (cli-opts [_ config opts] (conj opts [...] [...]))
3. don't include the config at all. then it's [dispatch-kw target].
4. have the defhook macro modify the arg list to include the the dispatch-kw itself. then writing a function/mm directly requires writing (defn some-hook [dispatch-kw config target] (case dispatch-kw :cli-opts (...))) while writing a hook is only (defhook some-hook (cli-opts [config target] ...))
i think the second way is the best way, but it feels bad to not "hide" the dispatch value in some way. i hate exposing it like that, it's a useless arg
This is because the hook is essentially a generic thing and the dispatch keyword is one of a fixed set of "lifecycle" points in LazyTest itself?
If that is the case, 4. seems like the "best" option, insofar as it matching the semantics of the domain (lifecycle hook, identified via symbol name that is implemented via a mapping to a keyword under the hood)?
yes. the hook is merely a function (can be a multimethod but doesn't have to be) that's held in a vector, and at every run-hook call, it executes all of the loaded hooks with the config and target object
And it's up to the hook's implementation to only fire for the lifecycle event(s) it cares about? So it's inherently a case under the hood, with one (or more) dispatch keyword clauses?
yes
(because the lifecycle is a fixed set of keywords identifying the hookable points)
yes
Okay, then I'm more convinced 4. is the better option.
Allowed hook methods:
* cli-opts
* config
* pre-test-run
* post-test-run
* pre-test-suite
* post-test-suite
* pre-test-case
* post-test-casefor prior art, kaocha handles this by not using multimethods lol. it creates standalone functions, a var map of {hook-kw func}, and then calls (defmethod -register plugin-id [plugins (conj plugins var-sym)) (in a macro)
that means each function can have a custom argument list
that's not a bad way to do it, but i don't mind requiring some regularity (and would include the config in all calls anyway)
i think you're right that 4 is the best option. folks writing the functions/mm manually can just include the dispatch-kw arg, and folks using defhook won't notice
(instead of filling the whole channel as i did yesterday, i'll try to keep this discussion in the thread above)
shout out to the kaocha docs authors, this is way better than the stuff i'm writing