Testing Helpers in Padrino
This article is part of an ongoing series about my exploration of the Padrino web framework. If you want to read more about it please check out padrinobook.com. You sniff around in the sources of the book under GitHub.
I always was wondering how to test helpers in Padrino and to be honest I postponed this problem for a long time. But this morning I reached the point in my book where I was writing helper with many methods without testing them. When something like this happened you have stop going and spend time to solve this problem.
The Problem
Let’s say you have a typical Padrino helper:
# app/helpers/users_helper.rb
JobVacancy::App.helpers do
def foo
"bar"
end
end
You can use the foo
method anywhere in you controllers and views. But what happened if your helper is getting more and more complex like the following one:
# app/helpers/users_helper.rb
JobVacancy::App.helpers do
def current_user=(user)
@current_user = user
end
def current_user
@current_user ||= User.find_by_id(session[:current_user])
end
def current_user?(user)
user == current_user
end
def sign_in(user)
session[:current_user] = user.id
self.current_user = user
end
def sign_out
session.delete(:current_user)
end
def signed_in?
!current_user.nil?
end
end
Right, there is a lot of stuff inside and you need to test this.
Assumption
Let’s say you have the following structure within you application:
.
├── app
│ ├── controllers
│ │ ├── ...
│ ├── helpers
│ │ ├── users_helper.rb
│ │ ├── ...
│ ├── models
│ └── ...
├── spec
│ ├── app
│ │ ├── controllers
│ │ │ ├── ...
│ │ ├── helpers
│ │ │ └── users_helper_spec.rb
│ │ ├── models
│ │ │ └── ...
│ ├── spec_helper.rb
And you have written your helper in the typical helper style of Padrino which are generated when you create a new controller:
# app/helpers/users_helper.rb
JobVacancy::App.helpers do
def foo
"bar"
end
end
This syntax is a shortcut for:
helpers = Module.new do
def foo
"bar"
end
end
JobVacancy::App.helpers helpers
In Padrino, helpers are generally an anonymous module. Testing something anonymous isn’t possible. To make this helper testable we need to make this module explicit:
# app/helpers/users_helper.rb
module UsersHelper
def foo
"bar"
end
end
JobVacancy::App.helpers UsersHelper
You can still use the foo
method everywhere in your views and controller. But now you’ve got a big plus. You can test it.
Prepare the Spec
We need to require the helper in our spec_helper
:
# spec/spec_helper.rb
PADRINO_ENV = 'test' unless defined?(PADRINO_ENV)
require File.expand_path(File.dirname(__FILE__) + "/../config/boot")
require File.dirname(__FILE__) + "/../app/helpers/users_helper" # <--- this is what we need
RSpec.configure do |conf|
...
conf.full_backtrace= false
conf.color_enabled= true
conf.formatter = :documentation
end
Write the spec
And here is a spec for that:
# spec/app/helpers/users_helper_spec.rb
require 'spec_helper'
describe UsersHelper do
before do
class UsersHelperClass
include UsersHelper
end
@user_helper = UsersHelperClass.new
end
it "test foo" do
@user_helper.foo.should == "bar"
end
end
We create a class in the before part of the spec which include our UsersHelper
module. Next, we are creating the instance variable @user_helper
as a new object of our class UsersHelperClass
. Running our tests will make unicorns happy and fast:
$ rspec spec/app/helpers
UsersHelper
test foo
Finished in 0.00041 seconds
1 example, 0 failures
I’m quiet sure that there is a better way to write the spec. If you know a way, please let me know.