A glaring hole in the Test Driven Development aspirations of Rails is helper tests. And also view tests, which Eric Hodel is working on.
But back to helper tests….you can test them somewhat through your functional tests, but how can you test them individually?
Ryan Davis figured out a solution and I made it into a plugin!
Installation is simple:
./script/plugin discover ./script/plugin install helper_test
You can generate a test for the ApplicationHelper by running the generator:
./script/generate helper_test Application
Finally, require the helper_testcase in your test_helper. There is a commented line in the helper_testcase that you can copy and paste into your test_helper.
require File.expand_path(File.dirname(__FILE__) + '/helper_testcase')
The files are generated inside the test/unit/helpers folder and will be run when unit tests are run.
It’s that simple!
Within the application_helper_test.rb, you can call a helper method and check the output.
def test_show_page_nav
output = show_page_nav
assert_match %r{Cloneberry International}, output
end
I like to save the output of the method so I can do several tests against it without having to call it again. Others like to call it once and do an assert_equal against the entire string.
Only a few helpers libraries are included in the parent class. If your helper calls a helper in Rails that is not listed, you can add it to the list.
# Add other helpers here if you need them include ActionView::Helpers::ActiveRecordHelper
It feels better to be writing tests. Adding helper tests makes it that much more thorough. You know you’re doing the right thing.
So go write some tests and start feeling good!
dude, topfunky++
Geoff,
Looks simple, I need to step up my test-game.
FYI, I got the dreded “Application Error(Rails)” the first time my RSS client (Thunderbird) tried to read this post. 30 seconds later it was fine. Maybe worth a log check?
Doh, now I got it again when submitting my comment from Thunderbird. We’ll see how submitting from firefox goes…no dice try 1. Try #2…Try #3…#4…
Yeah, I see a few 500 errors.
I’ll check it out, and maybe upgrade to Rails 1.1.1 and the latest Typo to see if that helps.
You realize I’m totally stealing this for Test::Rails.
Yeah, we thought that might happen.
Steal it!
Geoff, just thought I’d mention (having just tried this) that the files this plugin generates are named bad – if you rename helper_testcase.rb to helper_test_case.rb then Rails will automagically pick it up.
Great stuff though :)
Fascinating. I didn’t know it would work that way, but I’ll try it.
Ok…you’re right, but you still need the “require” if you are going to run tests individually.
I use TextMate’s built-in command-shift-R to run single tests, and it only works if helper_test_case.rb is explicitly required in test_helper.rb.
I’ll change the plugin to use your suggestion anyway, and TextMate users can add the extra require, if needed.
Geoff,
So speaking of plugins, what are the plugins you just couldn’t live without? I haven’t really found anything out there for rail plugins like say, firefox extensions. What do you recommmend? And is there a place that shows what others do?
weird, I can’t run the ‘script/plugin discover’ command.. when I run it, I get a list of URLs to confirm and finally:
Add http://jthopple.textdriven.com/svn/public/rails/plugins/? [Y/n] (eval):3:in `each': undefined method `[]' for nil:NilClass (NoMethodError) from /usr/lib/ruby/gems/1.8/gems/rails-1.0.0/lib/commands/plugin.rb:627:in `scrape' from /usr/lib/ruby/gems/1.8/gems/rails-1.0.0/lib/commands/plugin.rb:601:in `parse!' from /usr/lib/ruby/gems/1.8/gems/rails-1.0.0/lib/commands/plugin.rb:600:in `parse!' from /usr/lib/ruby/gems/1.8/gems/rails-1.0.0/lib/commands/plugin.rb:411:in `parse!' from /usr/lib/ruby/gems/1.8/gems/rails-1.0.0/lib/commands/plugin.rb:427:in `parse!' from /usr/lib/ruby/gems/1.8/gems/rails-1.0.0/lib/commands/plugin.rb:823 from /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:21:in `require' from /usr/lib/ruby/gems/1.8/gems/activesupport-1.2.5/lib/active_support/dependencies.rb:214:in `require' from script/plugin:3any help would be greatly appreciated, thanks! :)
Hmmm…I tried that url and I couldn’t reproduce the bug (it worked).
What version of Ruby? Have you upgraded RubyGems lately?
Very unfortunately its totally breaks in Rails 1.2.2, thought it worked beautefully in 1.1.6. Also, was that included in Rails 1.2 directly, because its really a super awsome plugin
ruby-1.8.5/lib/ruby/gems/1.8/gems/activesupport-1.4.1/lib/active_support/dependencies.rb:249:in `load_missing_constant': Expected /usr/local/RailsProjects/rails_apps/cmws/config/../app/helpers/cmws_helper.rb to define CMWSHelper (LoadError) from ruby-1.8.5/lib/ruby/gems/1.8/gems/activesupport-1.4.1/lib/active_support/dependencies.rb:452:in `const_missing' from ruby-1.8.5/lib/ruby/gems/1.8/gems/activesupport-1.4.1/lib/active_support/dependencies.rb:464:in `const_missing' from ruby-1.8.5/lib/ruby/gems/1.8/gems/activesupport-1.4.1/lib/active_support/dependencies.rb:260:in `load_missing_constant' from ruby-1.8.5/lib/ruby/gems/1.8/gems/activesupport-1.4.1/lib/active_support/dependencies.rb:468:in `const_missing' from ./test/unit/helpers/cmws_helper_test.rb:9 from ruby-1.8.5/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require' from ruby-1.8.5/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `require' from ruby-1.8.5/lib/ruby/gems/1.8/gems/activesupport-1.4.1/lib/active_support/dependencies.rb:495:in `require' from ruby-1.8.5/lib/ruby/gems/1.8/gems/activesupport-1.4.1/lib/active_support/dependencies.rb:342:in `new_constants_in' from ruby-1.8.5/lib/ruby/gems/1.8/gems/activesupport-1.4.1/lib/active_support/dependencies.rb:495:in `require' from -e:1 from -e:1:in `each' from -e:1Just wind up using recipe 44, it works well in Rails 1.2
Is it possible to use ‘assert_select’ against a helper methods output? This would seem to be the natural approach but at first glance I could not assert_select to work for partial ouput.
I have found that, in fact, you can use
assert_selectquite easily. Simply do the following:@response = ActionController::TestResponse.newinto the HelperTestCase#setup@response.bodyThe following example demonstrates:
I also found that when using the
content_tagmethod to generate html, I needed to also include the CaptureHelper and TextHelper modules. By the way, passing a block to content_tag will cause an error when run from the test case. This problem has been documented.Great stuff. In case it helps anyone else, on a machine that still had ruby 1.8.4 on it we were seeing:
Come up during test runs. Upping to 1.8.6 fixed this, so I assume something changed in the standard lib test/unit.
Hmm. My last comment was wrong, that error actually seems to be related to running the tests with autotest (ZenTest) and it not being able to find the test to re-run it.
Also, I noted that while this post says it was published 6/13/07 it isn’t actually current and shows up on your archive page as from April 2006? Can anyone toss a pointer to whatever the most current suggested method of testing helpers is?
Thanks much.
That error is indeed with Autotest, but there’s a better way. The ZenTest gem includes Test::Rails, which is capable of testing your helpers separately from your views.
Or, rSpec has Helper spec’ing built-in.
Thanks!
I am unable to figure out how to get ZenTest to actually do any kind of real testng with helpers.
Could you give a pointer or two?
This broke for me upgrading from 2.0.1 -> 2.0.2 … setup method does not get called with Test::Unit. Haven’t been able to figure out any more yet, unfortunately. Ugly work around is to call a setup method in each test case. You can’t call this method ‘setup’ either, so maybe it’s getting aliased somewhere.
Did some more looking, it seems rails is aliasing the setup method in
vendor/rails/activerecord/lib/active_record/fixtures.rbwhich I suspect is causing issues. In my helper, I changed the ‘setup’ method to ‘setup_with_fixtures’ (making sure I called super) and everything is fine. ‘setup’ inHelperTestCasestill gets called.@Xavier: Thanks for the troubleshooting. I’ll look into this tomorrow and issue an update.
Did some more research, maybe this will help: Test setup broken in Rails 2.0.2