Experiences on the Front Lines of User Interfaces and Web Development

How to Unit Test a custom Rails Form Builder

I recently created my first custom Rails builder.  It was very easy to do.

First, create a class that inherits from ActionView::Helpers::FormBuilder and then you can either write your own methods or overwrite the built in text_field, check_box, radio_button, etc.
class MyFirstFormBuilder < ActionView::Helpers::FormBuilder
...
end

Then, when using a form you can specify the builder (or set your builder to be the default in your config file)
<% form_for @post, :builder => MyFirstFormBuilder do |f| %>
...
<% end %>

That's all great and well documented, but I had a hard time finding the best way to write automated tests for the builder.  I was looking for a way to write unit tests directly against this class, rather than relying on a view and controller and using the heavier functional test framework.  Here is how it is done:

require File.expand_path('../../test_helper',  __FILE__)

class MyFirstFormBuilderTest < ActionView::TestCase
tests ActionView::Helpers::FormHelper

def protect_against_forgery?
false
end

test_error_messages_format_when_no_errors
assert @post.valid?

form_for(:advertiser, @post, :url => "/foo",
                                 :builder => MyFirstFormBuilder) do |f|
concat f.error_messages
end

assert_dom_equal "<form action="/foo" method="post"></form>",
output_buffer
end
end


The keys are:
1. Inherit your unit test from ActionView::TestCase
2. tests ActionView::Helpers::FormHelper is key to allow you to directly call helper methods that you normally would call from an ERB template file (such as form_for)
2b. I had to define protect_against_forgery? in order to call form_for
3. output_buffer is an accessor of ActionView::TestCase, which is an HTMLDocument object of the output
4. assert_dom_equal is handy to compare HTML output for equality (ignoring attribute order and single quotes versus double quotes)
comments powered by Disqus