Generating and Testing Behaviors
Radiant ships with a custom generator for behaviors. Let’s have a look at it in action:
% script/generate behavior HelloWorld
exists app/behaviors/
exists test/unit/behaviors/
create app/behaviors/hello_world_behavior.rb
create test/unit/behaviors/hello_world_behavior_test.rb
Open hello_world_behavior.rb. You will see that the generator has created a nice skeleton for your new behavior:
class HelloWorldBehavior < Behavior::Base
register "Hello World"
description %{
Describe Hello World behavior here.
}
end
As noted in the previous article about behaviors, the first line in the behavior registers the behavior under the “Hello World” name. This means that it will now show up in the behavior combo box on the edit page screen. The description slot is a place for you to describe what the behavior does. Eventually, you will be able to access these descriptions from the interface, but for now they only show up in code.
Now open up hello_world_behavior_test.rb:
class HelloWorldBehaviorTest < Test::Unit::TestCase
test_helper :behavior_render
def setup
@page = Page.new(:title => 'Test Page', :slug => "\\")
@page.behavior_id = 'Hello World'
@behavior = @page.behavior
end
# Replace this with your real tests.
def test_title_tag
assert_renders 'Test Page', '<r:title />'
end
end
The generator has created already created a nice test case for you. Replace the test_title_tag method with the following code:
def test_hello_tag
assert_renders 'Hello World!', '<r:hello />'
end
Now run your unit test:
% ruby test/unit/behaviors/hello_world_behavior.rb
Loaded suite test/unit/behaviors/hello_world_behavior_test
Started
F
Finished in 0.240644 seconds.
1) Failure:
test_hello_tag(HelloWorldBehaviorTest)
[/Users/jlong/Workspaces/radiant/trunk/radiant/test/helpers/behavior_render_test_helper.rb:5:in `assert_renders'
test/unit/behaviors/hello_world_behavior_test.rb:13:in `test_hello_tag']:
<"Hello World!"> expected but was <"<div><strong>undefined tag `hello'</strong></div>">
1 tests, 1 assertions, 1 failures, 0 errors
Whoops! Our first failure. This is actually just what we want because we are doing test first development. As you can see the test case is complaining because we haven’t defined the hello tag. Let’s do that now. Open up hello_world_behavior.rb again. Add the following block to the HelloWorldBehavior class underneath the description:
define_tags do
tag 'hello' do
'Hello World!'
end
end
Now run the unit tests again:
% ruby test/unit/behaviors/hello_world_behavior_test.rb
Loaded suite test/unit/behaviors/hello_world_behavior_test
Started
.
Finished in 0.161996 seconds.
1 tests, 1 assertions, 0 failures, 0 errors
Wow. Look at that! They passed on the first try!
Let’s make the hello tag a little more robust. I would like to be able to specify the name of the person in the tag. First, we should update the unit test. Add the following code to the test case:
def test_hello_tag_with_name_attribute
assert_renders 'Hello John!', '<r:hello name="John" />'
end
And watch it run:
% ruby test/unit/behaviors/hello_world_behavior_test.rb
Loaded suite test/unit/behaviors/hello_world_behavior_test
Started
.F
Finished in 0.218689 seconds.
1) Failure:
test_hello_tag_with_name_attribute(HelloWorldBehaviorTest)
[/Users/jlong/Workspaces/radiant/trunk/radiant/test/helpers/behavior_render_test_helper.rb:5:in `assert_renders'
test/unit/behaviors/hello_world_behavior_test.rb:17:in `test_hello_tag_with_name_attribute']:
<"Hello John!"> expected but was <"Hello World!">
2 tests, 2 assertions, 1 failures, 0 errors
Beautiful! Another failure! Test::Unit is complaining because the assert_renders assertion expects “Hello John!”, but instead it got “Hello World!”. Let’s fix that now. Open up hello_world_behavior again and replace the hello tag with the following code:
tag 'hello' do |tag|
name = tag.attr['name'] || 'World'
"Hello #{name}!"
end
And run your tests:
% ruby test/unit/behaviors/hello_world_behavior_test.rb
Loaded suite test/unit/behaviors/hello_world_behavior_test
Started
..
Finished in 0.197866 seconds.
2 tests, 2 assertions, 0 failures, 0 errors
Whew! Tests pass. This means that we’ve succeeded in creating a behavior with a hello tag which has a nice attribute called name in which we can specify the name of the person that we want to say hello to. You may want to fire up Radiant now and test it out.
If you create an interesting behavior that you would like to share with others, please announce it on the mailing list and add it to the third-party behaviors page. Unit tested behaviors may be eligible for inclusion in the core.
