Rails Class Collisions
August 23rd, 2008
While trying to use Integrum’s oh-so-nifty missing spec finder on a recent project, I discovered that it was not working. Hmmm… seems that somewhere along the way Rails added detection for existing constants and won’t allow you to re-generate something. Instead it calls raise_class_collision, which raises a UsageError. Damn them.
Anyway, to work around this for now, you can add the following somewhere (e.g., an initializer):
require 'rails_generator/base'
require 'rails_generator/commands'
module Rails
module Generator
module Commands
class Create
def raise_class_collision(class_name)
# Do Nothing
end
end
end
end
end
This should get around that inconvenience. Plus, you won’t be exposed to nefarious suggestions like I was:
$ rake spec:sync
The name 'User' is either already used in your application or reserved by Ruby on Rails.
Please choose an alternative and run this generator again.
Suggestions:
exploiter
drug user
substance abuser
Thanks Rails, you’re so helpful! I just don’t understand how it could have known I was building a Facebook clone for junkies…
Other Resources
Discover your missing specs
September 4th, 2007
Have you ever had the feeling that something was missing, but you weren’t quite sure what it was? I was looking at my code coverage the other day and thought to myself that it seemed like I was missing something. Rather than go through each file manually to see if it had an associated spec, I created a small rake task that does this for you.
The rake task looks at all the files in your app directory and tries to find an associated file in the spec directory. It follows the current Rspec generator naming conventions and if it doesn’t find the associated file it runs the generator to create it. It assumes that your app directory and spec directory follow the same directory structure and that you should at least have one test file for every application file.
You may find this as part of the Rake Tasks plugin over at Integrum.
To install:
script/plugin install http://svn.integrumtech.com/public/plugins/rake_tasks/
OR
piston import http://svn.integrumtech.com/public/plugins/rake_tasks/ vendro/plugins/rake_tasks
(Piston is one of my new favorite tools)
My additions are two rake tasks:
rake spec:check # Check files in the app directory for corresponding test files in the spec directory.
rake spec:sync # Check for missing test files in the spec directory and create them if they don't exist.
If you’re using Subversion, then you can also use the Subversion tasks that come with the Rake Tasks plugin to add the new spec files to your repository:
rake svn:add # Adds new files to subversion
rake svn:remove # Removes missing files from subversion
rake svn:ignore # Configures svn:ignore properties on log, tmp, db/schema.rb and config/database.yml
rake svn:conflicts # Resolves all svn conflicts by keeping the working file
This plugin was also the original home of some tasks that you may already be familiar with (I use them all the time):
rake db:create # Creates the databases defined in your config/database.yml (unless they already exist)
rake db:drop # Drops the database for your currenet RAILS_ENV as defined in config/database.yml
rake db:reset # Drops, creates and then migrates the database for your current RAILS_ENV
Those three were merged into Rails edge in May of this year.
Thanks to Josh Knowles, Derek Neighbors, and Josh Huckabee for their feedback on the addition. If you have any comments, bugs, patches, questions, etc. please send them my way.
Striving for 100 percent
August 22nd, 2007
If it wasn’t obvious from my last two posts I’ve been doing a lot of testing. In fact, I spent almost the entire day yesterday writing tests. This got me thinking about the value of testing.
With the testing I’ve done recently, I feel like I’ve uncovered several problems that would have made it through to production. This is good. Testing first forces you to think about what you’ll be developing before you ever develop it. I think this has helped me to write better code and, to me, this has value.
However, when I consider the quest for attaining 100% code coverage I start to waffle on the value of that activity. It seems like a blind generalization such as “we must have 100% code coverage” is neither practical nor valuable. When it comes to coverage, it seems that high profile functionality should be well tested, probably 100% covered. High profile functionality being functionality that is executed easily and often, functionality with high consequences, etc. But does it really make sense to spend a lot of time trying to get code coverage on something that will probably never happen and where, even if it does, it has little to no impact on the system? To me, this doesn’t seem like a valuable activity. If it’s easy to test, then go for it. But if it starts to become a time-sink then it might be time to think about whether you’re really adding value.
If testing should be as easy to do as not, then should 100% really be the goal? Is not striving for 100% a cop-out?
Testing a helper with a block
August 21st, 2007
I’ve been doing a lot of Rspec testing lately. Although I’ve been using it for a while to do BDD I realize that I have not been testing things as well as I should. Yesterday I was trying to add tests for a helper method that ensures the passed in block is only output if the user is logged in and an administrator. It’s a fairly simple helper method.
def admin_accessible(&block)
if logged_in? and current_user.admin
concat(capture(&block), block.binding)
end
end
I stumbled in the test though as I was unsure of how to test a helper that accepts a block. With the help of my colleague we came up with the following two solutions to this problem.
describe ApplicationHelper, 'invoke admin_accessible helper, when logged in as admin' do
before(:each) do
@user = mock("user")
@user.stub!(:admin).and_return(true)
self.stub!(:logged_in?).and_return(true)
@block = "Testing admin_accessible"
end
# Solution 1
it 'shall return captured block' do
html = eval_erb <<-ERB
<% admin_accessible do %>
<div><%= @block %></div>
<% end %>
ERB
html.should have_tag('div', @block)
end
# Solution 2
it 'shall return captured block' do
_erbout = ""
html = admin_accessible do
_erbout << "<div>#{@block}</div>"
end
html.should have_tag('div', @block)
end
end
Do you know of a better solution?
Stubbing controller methods in a helper test
August 21st, 2007
I hadn’t created any tests of helper methods in Rspec until last week. Doing so I found that one of my helpers was invoking the restful_authentication logged_in? method. This probably isn’t a big thing, but I was unsure how to stub the logged_in? method, that is, how to get the controller context to be able to invoke the stub! method. What I learned from a colleague was that the context of the controller in a helper test is self.
self.stub!(:logged_in?).and_return(false)