
DRYing Elixir Tests with Macros - hugoribeira
http://hugoribeira.com/DRYing-Elixir-Tests-With-Macros/
======
moomin
This observation is orthogonal to the original article but: often DRYing tests
is a bad idea. Two principal reasons: 1) if you need a lot of boilerplate, you
might need to look at refactoring your classes to reduce dependencies 2) non-
DRY tests are often easier to read due to increased indirection.

None of which means that I don't reserve the right to DRY tests out when I
think it's contextually appropriate.

~~~
hugoribeira
I agree, you should be very careful about DRYing tests. Making sure and
endpoint touches the authentication layer seems like a very good case to break
that rule of thumb.

I've been writing Web Applications for a while now. There was only a handful
of cases where I needed to repeat the same test case over and over again
(authentication being one of them).

If it happens too often, it's a good tell that you're missing a responsability
delegation into a concrete module/class somewhere.

------
ninjakeyboard
This is a very cool demo of use of macros.

On testing, I think DRY principles are a good thing in your production code
but I don't believe there is anything wrong with having lots of repetition in
your test code. Each test can be read from front to back by the reader. If you
have to wander around trying to understand the design of the test then that
may not be ideal. Shouldn't need unit testing for your unit tests :P

------
luiz-pv9
I'm always very careful when placing code supporting the test outside of the
test itself. Setup and teardown functions are fine, but I prefer to be safe
because, well, you can't test the test.

\-- I'm not saying this is the case in the blog post. Just some thoughts.

~~~
jtmarmon
If a macro used for a test suite is substantial enough and used often I'd say
it's worth testing

------
pmarreck
I think this would be done better as a private function that takes a conn, a
method, an action and an expected response code.

No need to complexify things unless you absolutely must.

~~~
rozap
Agreed. Elixir's first rule of macros is to not use macros. Generally
idiomatic elixir is to try to encapsulate your problem in (ordered by
priority) a 1) data structure 2) function 3) macro. So if you can express your
problem in something other than a macro, do so.

------
pesnk
Erlang/elixir is getting some awesome love from hacker news. <3

This is pretty sweet for testing repetitive tasks and also to get starting
with macros on elixir.

~~~
ad_hominem
Erlang has always done well on HN. One time the whole front page was Erlang
submissions after pg asked for more Erlang.

------
147
Was it not possible to simply write a function to achieve the same result?

~~~
hugoribeira
I don't think so, I believe the function calls need to be there at compile
time so that the test actually gets run.

But I'll give it a try tonight though :)

~~~
147
I don't think you can get the exact same syntax without using a macro. But
couldn't you have just your entire assertion in a function and pass in the
conn, method, route name, and expected json status?

Then you just wrap that in your test "..." form.

I don't see much gains from writing a macro, I see more drawbacks.

Pros of just using function and wrapping it in test form:

* It's just a function, easier maintenance. If you write a macro, you have to debug not only the macro but the code your macro writes.

* You gain more clarity into what each test is testing when there are failures. You hard code the "requires authentication" part as your test string. To write a macro that is flexible enough to also allow the user to specify the string here would end up defeating all purpose of it.

* You unquote the three arguments you pass in to the macro immediately. That's a red flag to me that this shouldn't need to be a macro. It's just to avoid the test boilerplate.

Cons:

* It's syntactically longer

I'm coming from a Clojure perspective, I've dabbled briefly with Elixir so let
me know if I'm wrong. I wanted to get into Elixir more but the community's
pervasive use of macros is keeping me from embracing it. They say Elixir is
less magical and more explicit than Ruby and while that's not an untrue
statement, I'm seeing too much metaprogramming already with macros. I'm not
saying all macros are bad, it's just the vast majority of them are unneeded.

~~~
matthewrudy
If you look at the code, that's actually what the author has done.

They've made a `make_unauthenticated_request` function that does the work, and
the macro just calls it.

But, I agree, I'd probably have skipped the macro. And DRYed it up with just
the function.

~~~
147
Right. That's exactly what I'm trying to point out. The point of the macro is
to get the test form stuff.

------
sjtgraham
I've been thinking of exactly the same thing over the last couple of days and
controller tests are prime candidates for this kind of DRY-ing, e.g. one would
want to make sure resources owned by a user are actually scoped to that user
and unaccessible to others. That is something that needs to be done on every
action. Perfect case for DRY-ing up.

------
rhinoceraptor
I like tests to be as unclever as possible, I want to know my tests are
actually testing the code and not passing incorrectly.

