

Testing Rake Tasks with RSpec - carlosplusplus
http://carlosplusplus.github.io/blog/2014/02/01/testing-rake-tasks-with-rspec/

======
lukes386
Interesting post, but that much scaffolding around the tests is a bit of a red
flag to me.

I personally try to move as much logic as possible into easily testable,
independent methods. This leaves things like Rake tasks as very small,
"obviously correct" shells around the actual logic.

I highly recommend checking out the talk Boundaries by Gary Bernhardt[0],
which explains this idea far better than I can.

[0]:
[https://www.destroyallsoftware.com/talks/boundaries](https://www.destroyallsoftware.com/talks/boundaries)

~~~
carlosplusplus
Thank you, lukes386, for your comment.

I'm new to Ruby / Rails and using RSpec in general, so I really appreciate any
resources people pass along. I'll be sure to check out that talk and may
refactor my tests accordingly.

------
rpwilcox
Kind of neat.

What I like to do with rake tests and/or delayed jobs is write the actual
business logic in some other file / module: a module in lib/, a DCI style
class, whatever. Then the delayed job / rake task just calls that code.

So your rake / Delayed Job interface is one, maybe two lines. And the body of
your code lives somewhere easily testable with standard unit tests without
having to mock out Rake (and/or forcing your asnyc queue mechanism to be
synchronous for testing).

~~~
carlosplusplus
Thank you for the great comment & suggestion, rpwilcox!

As you recommended, I'll be moving the majority of my actual rake task into a
DelayedJob which will perform all the work. The rake task will then only be
responsible for queueing up the batches of work and nothing else. And yes, at
that point, I could just test the DelayedJob itself vs. the actual execution
of the rake task, as I'd have a high degree of confidence that if the
DelayedJob works on a model as expected, it will work via DelayedJob in
batches.

I decided to write about this first to showcase the capability of explicitly
testing rake tasks - I started learning Ruby / Rails about 6 months ago and
wanted to share this knowledge. My follow-up post will be on turning this into
a DelayedJob.

------
danso
This was a very useful writeup and am looking forward to your followup with
DelayedJob...but what would you say to people who think you could've made the
re-calculation methods part of the model? I guess you could argue that you
still would want to test any batch task as part of the integration though.

~~~
carlosplusplus
Thank you for your comment and question, danso.

The particular re-calculation method I presented in this blog post is
(hopefully) only going to be run one time, as it serves to recalculate fields
based on a database migration. Those fields are counter caches in my Rails
models, meaning that their values get +1 automatically when an Answer is
generated for a particular Question (approved or not).

Given the nature of the task at hand, I felt it was better practice to keep
the model 'clean' and abstract the computation to the rake task itself. The
computation will soon be extracted out to a DelayedJob, further isolating the
re-calculation method in a modular fashion.

Hope that answers your question!

