loading...

A tip for faster Rails Helpers Tests

bhserna profile image Benito Serna Originally published at bhserna.com ・3 min read

If you are here, maybe it is because you also like fast tests!... I really like fast tests, and for that reason (and some others...) I always try to decouple my code from Rails and other frameworks...

But, the reality is that if you are using Rails, you also need to write "Rails code"...

If you are like me and you simply cannot work if you need to wait for Rails to start... And you need to write tests for a Rails helper function, then you can follow this steps and write your helper function doing TDD with fast tests...

1. Do not require the rails_helper

In your test file instead of writing at the top...

require "rails_helper"

Try to require the file that you are testing and the stuff that you need.

For example If you are working in a function that will use the number_to_human helper. You could require just active support, instead of requiring all rails. Like this...

require "active_support"
require_relative "../../app/helpers/formats_helper" # this is the helper you are testing

2. Add a class that includes your helper and the helpers that it needs

In your test file inside the RSpec.describe block you can add a class an include the helpers that you need and the helper that you are testing.

Following the same example... If your function will use the number_to_human helper and that helper lives in the ActionView::Helpers::NumberHelper module, then you need to include that module and the one you are testing, like this...

require "active_support"
require_relative "../../app/helpers/formats_helper"

RSpec.describe FormatsHelper, type: :helper do # as in the specs https://relishapp.com/rspec/rspec-rails/docs/helper-specs/helper-spec
  class Helper
    include ActionView::Helpers::NumberHelper
    include FormatsHelper
  end
end

3. Expose a helper method

Now just create an instance of that class, and expose it to your test...

Like this...

require "active_support"
require_relative "../../app/helpers/formats_helper"

RSpec.describe FormatsHelper, type: :helper do # as in the specs https://relishapp.com/rspec/rspec-rails/docs/helper-specs/helper-spec
  class Helper
    include ActionView::Helpers::NumberHelper
    include FormatsHelper
  end

  attr_reader :helper

  before do
    @helper = Helper.new
  end
end

4. Write your function using TDD with fast tests =)

Now you can write your helper using TDD with fast tests.

require "active_support"
require_relative "../../app/helpers/formats_helper"

RSpec.describe FormatsHelper, type: :helper do # as in the specs https://relishapp.com/rspec/rspec-rails/docs/helper-specs/helper-spec
  class Helper
    include ActionView::Helpers::NumberHelper
    include FormatsHelper
  end

  attr_reader :helper

  before do
    @helper = Helper.new
  end

  it "transforms 1234 into 1K" do
    expect(helper.short_amount_format(1234)).to eq "1K"
  end

  #...
end

5. If you want, return to the default way

After you have finished, you can return the stuff that we added to let the file as in the docs...

require "rails_helper"

RSpec.describe FormatsHelper, type: :helper do
  it "transforms 1234 into 1K" do
    expect(helper.short_amount_format(1234)).to eq "1K"
  end

  #...
end

And that's all for now =) ... I hope you can use it and feel the difference!


If you also like fast tests and want to learn how you can design your code to decouple it from Rails and frameworks in general... maybe you could be interested in a book/guide that I am calling Spec by Spec to help you do TDD with a use case approach.

Discussion

pic
Editor guide
Collapse
dangolant profile image
Daniel Golant

Interesting topic! In your experience, how much time has this shaved off your tests? I am not sure that this is the bottle neck in a test suite I work with, but I’m curious to hear if it’s worth giving a shot.

Collapse
bhserna profile image
Benito Serna Author

This is not really a tip to improve the time of your whole test suite... is mostly a tip to be able to do TDD on a helper in a faster way.

This are some results in my machine...

  • Using requiere "rails_helper"...
Finished in 5.66 seconds (files took 8.85 seconds to load)
21 examples, 0 failures

Randomized with seed 36477


real   0m15.406s
user   0m7.568s
sys    0m3.834s
  • Using the tip in the article...
Finished in 0.11966 seconds (files took 2.23 seconds to load)
21 examples, 0 failures

Randomized with seed 52780


real    0m3.157s
user    0m2.062s
sys     0m1.037s

Maybe for some people the difference is not that much... but I am use to do TDD without rails, and I really feel frustrated with slow tests =S...

For example our whole suite of use case tests, run like this...

Finished in 8.33 seconds (files took 3.69 seconds to load)
2371 examples, 0 failures

Randomized with seed 57751


real    0m12.863s
user    0m10.923s
sys     0m1.523s

We run more than 2000 tests in almost the same time than 21 tests for just a helper =S ... that why for me is helpful =)...

But really it will depend a lot on the size of the app you are working on and how much time it takes to start.

Collapse
dangolant profile image
Daniel Golant

Totally, it’s all relative. For what it’s worth, cutting helper tests from 5s to .1s is incredibly helpful!

Collapse
katafrakt profile image
Paweł Świątkowski

That's great way to test helpers and also immediately see if they are not too coupled. I tried to introduce such way of testing some time ago but the response was not too enthusiastic. Soon I learned that it's easier to convince people to take one more step forward and ditch using helpers at all ;)

Collapse
bhserna profile image
Benito Serna Author

I think thats a better tip =) ... Actually in this project we have no more than 10 custom helpers... but sometimes we think that helpers are the better solution.