Fork me on GitHub

I can't find letfn* on clojuredocs; besides the source code, is there any documentation ?


no, clojure internals aren't really documented


is there any good talk / blog post on various philosophies of unit testing? I feel like (after a few years of on/off) I'm finally starting to develop a philosophy. It goes something like this: 1. unit test every function 2. go for 100% coverage, make sure all exprs of all functions are executed by some test 3. the basic philosophy is: yeah, sure, this isn't as comprehensive as type checking, but if you have 100% coverage, it's hard to have obvious/simple errors, because there's atleast one non-trivial example on which it worked


as a result of this, I'm now moving towards really short functions + unit tests about 2-3 times as long as function, to get 100'% coverage there isn't really a question here, just hoping to get insights / philosophies of unit testing from others / suggestions


There’s an article somewhere that suggests going for 100% coverage can have unintended consequences. Namely, that your dev team will be tempted to skew their implementations solely for the purpose of making the code testable at the expense of clarity.


Yeah, 100% coverage is not a good goal, IMO.


perhaps I have not written any complex code yet, but 100% coverage seems simply a matter of: within each function, do as little branching as possible


There's a lot of stuff that's pointless to test. There is some stuff where you can describe expected invariants or properties of the code and exercise it in that context (generatively).


There's also a very big difference between "unit testing" and "test-driven development". I think the latter is much more valuable than the former.


@qqq I mostly only test the public contract of a module (the published API). And as much as possible I try to write those tests in a data-driven way.


So test.check or any random source of data are helpful there.


And I almost always write my tests after my code unless I'm adding a new feature that won't break any existing tests.


Fantastic reading. Thanks for the link!


As we were building out our new REST API, we wrote tests first to reflect the requirements doc, specifically to provide a framework for writing the validation and error reporting. That was back before clojure.spec -- now we write specs for a lot of things that we wrote tests for before 🙂


@tbaldridge: I'm not doing TDD. I wrote a small Joy/Forth interpreter in CLJ. Then I started defining Joy/Forth words, and reailzed: hmm, I should test each word. (So I'm testing after defining the word.) Then, because words are so simple, genrally 1-2 (sometimes 3-4) tests will hit 100% coverage.


Languages are quite unique in that respect.


My plan there is to use the same transforms as go but remove the nondeterminism. Then unit test "normal" clojure code that's gone through the transform. Probably not 100% coverage, but it's close


But I only ever write code like that when I'm working on a DSL/language


what would be a more idiomatic way to spec an heterogeneous/nested collection value? Current approach:

(spec/def ::pending-request-entry
  (spec/and vector?
            (fn [[id _]]
              (number? id))
            (fn [[_ x]]
              (vector? x))
            (fn [[_ [url _]]]
              (url? url))
            (fn [[_ [_ all-params]]]
              (all-params? all-params))))


possibly I could just refactor the heterogeneous vector into a map (for which having heterogeneous values is much more usual)


s/tuple is also just a vector (and is typically used for heterogeneous collections)


ah nice! never heard of it 👀


(I use one (fn ... per predicate, so spec/and can report the exact culprit)


any suggestions on how to have a cache in compojure?


There are many ways I think, you can use redis to memoize some functions, and maybe use flushdb to clean when you know the data is changed?


@gklijs I have no clue at the moment, I'm still trying to figure this out


an in-memory solution would suffice though


@erhardt.mundt assuming you want an arbitrary object cache for e.g. rendered html or DB records: I'd add a middleware ( ) that saves/fetches objects to a plain atom. Or a fancier in-memory cache like Bonus points if you wrap atoms/caches with so you have a cleanly reloadable dev experience. Non-battle-tested suggestion (middleware/atom) from my side, but seems reasonable


many thanks @vemv, it really seems to be a neat solution to the problem


my suggestion was based on what I remembered from You can't map 1-1 that tutorial to a plain compojure app, a more practical reading would be:


Anyone have strong preferences about graph libraries? Looking between loom, ubergraph, and jungerer. I know clojure libs tend not to break but it looks like loom looks like it hasn't been touched substantively this year so I'm curious if anyone has any endorsement/warning for this.


@bwstearns can be useful for questions like these - at least you can see how many other open source projects use each one


@noisesmith thanks for the lead.


I'd expect loom to have the most users, but it can be helpful to use real data and compare


Much appreciated.