Fork me on GitHub
#clojure-uk
<
2017-04-26
>
Rachel Westmacott08:04:00

random core function of the day:

-------------------------
clojure.core/with-redefs
([bindings & body])
Macro
  binding => var-symbol temp-value-expr

  Temporarily redefines Vars while executing the body.  The
  temp-value-exprs will be evaluated and each resulting value will
  replace in parallel the root value of its Var.  After the body is
  executed, the root values of all the Vars will be set back to their
  old values.  These temporary changes will be visible in all threads.
  Useful for mocking out functions during testing.

thanos18:04:27

oh yeah, I love that

thanos18:04:37

for testing only!

reborg08:04:32

If I see with-redefs outside test code I automatically go into alert mode. See an interesting snippets my team (cc: @omartell) recently pointed out:

(defn TEN [] 10)
(dorun (pmap #(with-redefs [TEN (fn [] %)] (TEN)) (range 100)))
(TEN)

mccraigmccraig08:04:34

random useful clojure thing i keep forgetting - keyword fns take optional default values

agile_geek08:04:27

@reborg Don't think I've ever used it outside of tests and even then it feels wrong

reborg08:04:46

@agile_geek perhaps. I use it a lot in tests tho, but not usually test first. It's when I come in in untested code, cover it a bit, refactor. Then usually the side effects get injected instead of staying deep in the call stack

agile_geek09:04:37

@reborg yeah test after the fact (which I'm doing a lot before making changes in existing codebase) is where I use it a lot. I have used it once or twice in my own code where separating the side effecty bit of a fn from a simple transform seems artificial but often I end up deleting the test in the end as it's all mock and no substance!

glenjamin09:04:39

Why does that pmap leak?

glenjamin09:04:56

I got 90 both times I tried it, is that consistent?

Rachel Westmacott09:04:09

I got a random number generator

mccraigmccraig09:04:05

i got different values each run @glenjamin

reborg09:04:12

the power of parallel threads competing 🙂

mccraigmccraig09:04:43

though they were all in the 90s, so perhaps not suitable for a cryptographic source of randomness

agile_geek09:04:37

I got 96 every time...don't you just love deterministic non-deterministic code

agile_geek09:04:03

imagine if you based an architectural decision on my result! WOMM

agile_geek09:04:19

Oh got an 85 that time! FTW!

maleghast09:04:30

I got 96 the first time I ran it, then 97...

mccraigmccraig09:04:08

i've gotten a couple of values down in the 50s... mostly 90s and 80s though... i've not seen any results below 50 yet

agile_geek09:04:19

We seem to have discovered an inverse Benford's Law number generator https://en.wikipedia.org/wiki/Benford%27s_law

mccraigmccraig09:04:28

stopping now. @reborg is a bad person who should feel bad

agile_geek09:04:27

Got a 1! I win!

agile_geek09:04:28

On a more interesting note I got caught out by Benford's law when trying to balance even loads across HBase clusters! I would have bene stuck for ages if I hadn't read about it before. Annoyingly I'd actually predicted this effect before starting the work but had completely forgotten about it!

mccraigmccraig09:04:00

oh, ok, it's easy

mccraigmccraig09:04:32

in other fun news, i discovered yesterday that ms-word was responsible for tripling our SMS bill

maleghast09:04:59

Today is another day in the saga of my wanting to "do" things with Datomic and finding Datalog completely non-intuitive...

maleghast09:04:16

@mccraigmccraig - How the blazes did that happen?

mccraigmccraig09:04:42

it had put an em-dash — into a sentence instead of a -, and since the em-dash isn't in the GSM7 character set our texts were being sent in UCS2, meaning 3 message segments for 150 chars of message instead of 1. changing the — to a - and the messages gets GSM7 encoded and takes only a single message segment

agile_geek09:04:47

@mccraigmccraig SMSing entire MS-Word docs?

maleghast09:04:10

@mccraigmccraig - That is a "special" edge case...

maleghast09:04:46

Also another reason to hate MS-Word and the MS em-dash

mccraigmccraig09:04:44

@maleghast you get your head around datalog after a bit - i haven't used datomic for more than a brief play, but i did a lot of stuff in cascalog a while back and it does become intuitive

maleghast09:04:28

I am reaching my limit of frustration not being paid-off by "good things" at the moment... 😉

Sam H09:04:04

In regards to avoiding with-redef in testing. Am I understanding it correctly in that you write you functions to take in depending functions but then you still need to use with-redef to test when you actually put everything together at a higher level? Any example projects/code/resources you recommend looking at?

dominicm09:04:15

@tbaldridge suggests not using with-redef even in tests. Because if those tests do any kinds of threads (promises, futures, etc.) they won't work.

dominicm09:04:30

Dynamic vars & argument passing are always the way to go, apparently.

dominicm09:04:38

I think it's okay to mark a var as dynamic for testing purposes.

agile_geek09:04:07

@shan simplistically if all your fn's are pure you can test the whole stack without mocking anything

glenjamin09:04:04

with-redefs is global, so should be fine as long as you don’t do multiple tests at once

Sam H09:04:19

what do you do when you’ve got a database call?

dominicm09:04:45

You have it on the edges of your code

dominicm09:04:07

You have a fat "middle" which is pure, and an outer ring of impure that does the db.

glenjamin09:04:15

and choose not to test the impure bits?

dominicm09:04:26

That's one option.

mccraigmccraig09:04:34

you still gotta test the db-related code

dominicm09:04:55

You could just avoid testing altogether 😀

dominicm09:04:37

If you're doing a full "integration" test to ensure your system mutates the db correctly, you don't want to mock things anyway, right?

mccraigmccraig09:04:27

not so - say i'm e.g. testing notifications get sent to the right users (who don't have any applicable mutes set) - i want to interact with the db, where all the user state is, but i want a mock notification service so i can examine the results

Sam H09:04:09

Are there any open source projects you lot recommend that has good test examples? or talks or blog posts?

mccraigmccraig09:04:46

but i side with @tbaldridge in that the way to get your mocks in is by argument passing and dynamic vars on occasion, subject to the rules of dynamic var club

glenjamin09:04:35

it’s a pain sometimes

glenjamin09:04:54

unless you have some monadic context i guess

glenjamin09:04:17

even then, what’s the difference between that and a global variable if you only run one thing at a time?

mccraigmccraig09:04:15

well, global variables in a component are ok until you come to use multiple instances of a component etc - using closures to capture your dependencies isn't going to bite you in the future

glenjamin09:04:10

the most easily overlooked one IME is time

mccraigmccraig09:04:41

what dyu mean ?

glenjamin09:04:02

system time is a dependency which should ideally be injected

minimal10:04:52

expectations has a handy freeze-time macro

minimal10:04:15

only works with joda iirc

glenjamin10:04:28

yep, and thats effectively a global override as well

dominicm10:04:21

java time has clocks, which is the new way to get now

dominicm10:04:24

and can be passed around

minimal10:04:53

i usually only use with-redefs to add tests to old code that wasn’t written with testing in mind