Fork me on GitHub
#clojure
<
2017-12-24
>
qqq00:12:54

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

bronsa00:12:42

no, clojure internals aren't really documented

qqq02:12:31

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

qqq02:12:43

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

gonewest81803:12:03

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.

seancorfield03:12:22

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

qqq03:12:45

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

seancorfield03:12:27

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).

seancorfield03:12:07

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.

tbaldridge03:12:23

@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.

tbaldridge03:12:49

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

tbaldridge03:12:55

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

jumar08:12:20

Fantastic reading. Thanks for the link!

seancorfield04:12:12

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 🙂

qqq06:12:17

@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.

tbaldridge14:12:24

Languages are quite unique in that respect.

tbaldridge14:12:50

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

tbaldridge14:12:13

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

vemv18:12:28

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))))

vemv19:12:56

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

johanatan04:12:23

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

vemv10:12:31

ah nice! never heard of it 👀

vemv18:12:17

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

ErhardtMundt19:12:12

any suggestions on how to have a cache in compojure?

gklijs19:12:05

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?

ErhardtMundt19:12:04

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

ErhardtMundt19:12:48

an in-memory solution would suffice though

vemv19:12:39

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

ErhardtMundt19:12:09

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

vemv21:12:30

my suggestion was based on what I remembered from http://docs.arachne-framework.org/tutorials/dependency-injection/ You can't map 1-1 that tutorial to a plain compojure app, a more practical reading would be: https://gist.github.com/Deraen/9d65f447593859dd07ae

bwstearns22:12:20

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.

noisesmith22:12:23

@bwstearns http://crossclj.info can be useful for questions like these - at least you can see how many other open source projects use each one https://crossclj.info/ns/jungerer/0.1.1/project.clj.html

bwstearns22:12:00

@noisesmith thanks for the lead.

noisesmith22:12:51

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

bwstearns23:12:52

Much appreciated.