form_test_helper, select_form update
on April 02, 2008 @ 05:28 PM
Revision 71 of form_test_helper includes a bug fix for the select_form method. Previously calling select_form with a block would submit the form. The fix forces you to call submit on the form. So…
1 2 3 4 5 6 7 8 9 10 |
# THIS which used to submit the form form = select_form 'trip' do |form| form.trip.destination = "bahamas" end # WILL NOW LOOK LIKE THIS form = select_form 'trip' do |form| form.trip.destination = "bahamas" end form.submit |
This doesn’t affect the usage of submit_form which still acts as expected.
This will be included in the next release of form_test_helper. Currently trunk for form_test_helper works with Rails 2.0.0 and higher (including today’s most recent trunk commit).
The form_test_helper edge docs have been updated as well and can be found here
Rails Ticket #11491
on April 01, 2008 @ 12:46 AM
If you have a few minutes, please review and comment on Rails ticket #11491.
http://dev.rubyonrails.org/ticket/11491
In short, it adds the ability for “render :partial => some_collection” to render the correct partial based on each element in some_collection. Currently Rails uses the first element to determine what to render for every element in the collection.
Thanks in advance,
Trying RSpec's Rubyesque Stories
on March 05, 2008 @ 12:35 AM
Today my pair and I wrote some stories using the rubyesque RSpec story style along with a corresponding step file. It went better then expected. We ended up a story like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
# in stories/expenses/a_user_creating_a_misc_expense_story.rb Story "User creating misc. expense", %| As a user I want be able to submit an expense reimbursement request for a misc. expense so that I can be reimbursed for business expenditures|, :steps_for => :expense, :type => RailsStory do Scenario "creating a misc. expense unsuccessfully" do Given "a user at a new expense reimbursement page" # .... end Scenario "creating a misc. expense successfully" do Given "a user at a new expense reimbursement page" # ... end end # in stories/steps/expense.rb steps_for :expense do Given "a user at a new expense reimbursement page" do go_to_root click_new_expense_reimbursement_link end # ... end |
Overall there are four story styles (that I’m aware of) in RSpec: plain text stories, rubyesque stories with separate step files, rubyesque stories with inlined steps and rubyesque stories with inlined blocks.
We did try using plain text stories at first, but one drawback of plain text stories is being able to run them individually from within your editor or easily from the command line. We didn’t have the need for plain text stories so we opted to not use it.
We started using the rubyesque stories with inlined steps secondly until we got a feel for the stories and then we moved those steps into their own file so we could achieve higher reuse and better step organization.
We knew coming in that we were not going to use the inlined block style since we have used that on another project and it gets clunky really fast.
If you’re considering using RSpec stories try the rubyesque stories with step matchers (inlined or in separate files). If you’re going to take the plunge into trying plain text stories look to RSpec itself for examples. The actual stories in the stories/ directory helped us get up and running earlier today.
form_test_helper edge gets support for multiple submit buttons
on November 27, 2007 @ 11:49 AM
form_test_helper edge has been updated to support multiple submit buttons on a form. It also includes a fix to avoid namespace collisions if models are named Select, Option, etc.
If you have a view which looks like:
1 2 3 4 |
<form id="test"> <input type="submit" value="yes" /> <input type="submit" value="no" /> </form> |
You can have choose which value to submit when the form is submitted:
1 2 3 4 5 6 7 8 9 10 11 |
# selecting the form and submitting it in separate steps form = select_form "test", :submit_value => "yes" form.submit # submitting a form with a submit value in one step submit_form "test", :submit_value => "yes" # submitting a form with a submit value in one step using a block submit_form "test", :submit_value => "yes" do |form| # .. end |
You don’t have to supply a :submit_value. If you don’t the first submit value found on the form will be used. If you try to supply a non-existent value then an exception will raised.
For example:
1 2 3 |
# trying to submit on a non-existent input value form = select_form "test", :submit_value => "fooey" form.submit # => raises a FormTestHelper::Form::MissingSubmitError |
Installing
As an external:
./script/plugin install -x http://form-test-helper.googlecode.com/svn/form_test_helper |
Not as an external:
./script/plugin install http://form-test-helper.googlecode.com/svn/form_test_helper |
With piston:
1 2 |
cd vendor/plugins/ piston import http://form-test-helper.googlecode.com/svn/form_test_helper |
Rdoc
Rdoc pages for form_test_helper edge are hosted on rubyforge. You can find them at http://continuous.rubyforge.org/form_test_helper/rdoc/
If you have any questions feel free to ask. If you find issues, bugs or odd behavior please create an issue over at http://code.google.com/p/form-test-helper/
form_test_helper 1.0.1 and 1.1.1
on November 27, 2007 @ 11:07 AM
form_test_helper 1.0.1 and 1.1.1 have been released.
- 1.0.1 is for people who are on 1.2.x (specifically 1.2.5 and 1.2.6)
- 1.1.1 is for people who are on a Rails Edge revision between 6764 and 7420
If you are on Rails Edge newer then 7420 then you’ll want to use form_test_helper edge. A separate announcement will be made for that release.
The 1.0.1 and 1.1.1 releases fix a namespace collision issue if you happen to have a model named Option or Select. Thanks to Tomasz Wegrzanowski for pointing this out and supplying a patch.
For information on how-to install, or for usage examples please check out the rdoc for these releases:
This will probably be the last release for the 1.1.x branch of development since it targets such as a small set of revisions on Rails Edge and it will be out of date shortly if it isn’t already.
test/unit story runner
on November 14, 2007 @ 01:53 AM
As you may know rspec has integrated RBehave into itself. In the rspec world it’s more recently been called Story Runner.
Some background links:
- Introducing RBehave
- User stories with RSpec’s Story Runner
- Story Runner in Plain English
- Plain Text Stories: Part III
Story Runner itself hasn’t officially been released and while it has been becoming more polished myself and a colleague (Drew Colthorp) wanted higher level acceptance tests in my ruby projects (including rails).
Story Runner also has two implementations (or at least APIs). The latest is the plain text Story Runner. This requires that for every story you have at least two files. One that is plain text for the customer to write and one that is a “matcher” file developers write. Information on this can be found here
The older version of Story Runner uses the original RBehave style syntax. Lots of blocks and lots of argument passing. There is also a bug in this implementation regarding sharing blocks given to story parts. But enough about rspec, this post is on a lighter weight and simpler Story Runner.
So here’s to a working and testing implementation of a Story Runner in test/unit.
test/unit Story Runner
To start, an example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
class EventCreationTest < ActionController::IntegrationTest fixtures :all Story "As a user I should be able to create an event so that others can RSVP and attend." Scenario "Creating an event unsuccessfully with insufficient input" do Given :a_user_at_the_create_an_event_page When :they_submit_the_create_an_event_form_with_insufficient_input Then :they_will_see_an_error_explanation And :they_will_see_the_create_an_event_page end # # HELPERS # def a_user_at_the_create_an_event_page # .... end def submit_the_create_an_event_form_with_insufficient_input # ... end def see_an_error_explanation # ... end def see_the_create_an_event_page # ... end end |
Some important things to note on the structure:
- the Story takes a description of the story. It does NOT take a block.
- multiple Story’s can be defined in a file although I prefer organizing them in separate files
- all Scenario’s which follow a Story will belong to that Story.
- the Scenario takes a description of the particular scenario or acceptance test for a story. It does take a block.
- inside of a Scenario you describe the story parts. These are Given, When, Then, and And.
Some important things to note on the story part descriptions:
- Each story part can take a string or symbol description
- helper method calls are generated off from the story part description
Helper method calls are generated by taking the full story part description and then removing the leading word until a helper method is found. If there are no helper methods found then an exception is raised.
Some important things to note on the goals of this implementation:
- in theory customers write acceptance tests
- in practice developers translate customer desires into acceptance tests
- ideally the acceptance tests should be high level enough that a customer can read/write them
- since developers will most likely write these acceptance tests this implementation should allow for developer shortcuts
- this should just work on a test/unit project, projects updating to this shouldn’t have to convert or make changes up front to existing code
script/plugin install
script/plugin install \ http://continuous.rubyforge.org/svn/tags/test_unit_story_runner-0.1.0
Final Thoughts
Before I forget you can do argument passing as well on story parts:
1 2 3 4 5 |
Scenario "a user successfully making a guess in the game" do Given :a_user_at_the_game When :they_make_a_guess_of, 20_000 Then :they_will_win_a_car end |
This feature is there, but I would advocate only using it when it helps the readability of your tests.
This is a stable (tested) experiment. It’s a thin wrapper around the test/unit framework and it works with any Test::Unit::TestCase. The price to pay for higher level acceptance tests is now next to nothing so give it a shot.
This is the creation of a trip to Madison, WI where Drew and I had a chance to discuss and vent about the state of acceptance tests in Rails projects specifically. A few days later we had this implementation, and about a month later you’ve got this post…
Suggestions and feedbacks are warmly welcomed.
Happy rubying!
Plain Text Story Running
on October 23, 2007 @ 09:16 PM
David Chelimsky announced yesterday the first implementation of Plain Text Stories.
http://blog.davidchelimsky.net/articles/2007/10/22/plain-text-stories-on-rails
More on this to come…
Story Runner - constructive ideas
on October 16, 2007 @ 08:38 PM
Yesterday I ranted on some criticisms that I have of RSpec’s Story Runner. This post will try to follow up the criticisms which an implementation I like.
The code we started with yesterday is:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
Story "View Home Page", %{ As a user I want to view my home page So that I can get a birds eye view of the system }, :type => RailsStory do Scenario "Latest published article" do Given "an author named", "Zach" do |name| @user = User.create! :name => name end When "he visits the home page", "/" do |path| get path end Then "he should see the latest article published front and center" do # ... do something to see the article shows as expeted end end end |
Here is a version of this that I like, and is implemented in test/unit story runner (which has yet to make its public debut):
1 2 3 4 5 6 7 |
Story "As a user I want to view my home page so that I can get a birds eye view of the system" Scenario "Latest published article" do Given "an author" When "he visits the home page" Then "he will see the latest article published front and center" end |
Story Description
It gets rid of the unnecessary description and :type parameters. It leaves only the story itself.
Story Do/End Blocks
It removes them. They are not needed. They provide unnecessary grouping which hurts readability for the customer.
Scenario Do/End Blocks
These are kept. These are the one area where I feel making a visual grouping is important for the customer and the developer. All Scenario’s will be attached to the Story declaration which precedes it.
Argument Passing
I removed the arguments from the original example. They weren’t providing value to my tests. I do believe argument passing is valuable but it must be in a way that adds value to the test. For example in a game I am ok with the 500_000 below:
1 2 3 4 5 |
Scenario "Becoming the top scorer" do Given "a player" When "he makes a guess of", 500_000 Then "he will see himself as the number one scorer" end |
It seems that a lot of cases where arbitrary arguments are passed can be updated to make their descriptions more meaningful. It can do this by describing what is under test based on what may influence the test. Typically a user’s name doesn’t do this. So rather then:
Given "a user named Zach" |
I’d rather see why “Zach” is special. Maybe he’s an admin:
Given "an administrator" |
The Process
I haven’t explained yet how test/unit story runner is implemented so bare with me. When you add a new Story or Scenario it looks like the example posted above.
When you change or update an existing Story or Scenario it still looks like the example posted above. There is no embedded code, or horrendous blocks following every declaration (just the Scenario one!).
Reusable Code
Here’s where a high level overview of test/unit story runner comes to fruition. It takes a story part’s (Given/When/Then/And) description and turns that into a helper method using a simple mapping process.
- take the description and downcase it
- strip out all punctuation
- then replace spaces with underscores
- look for the method name
- if it exists, execute it, otherwise strip the first word and repeat
So every story description maps to a method. And these methods can be included at the bottom of your story file or in a shared helper file (or both!).
Here’s a few example mappings:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
Given "an administrator" # => an_administrator When "he clicks the big button" # => clicks_the_big_button Then "he will see a picture" # => see_a_picture And "he will see another button!" # => see_another_button def an_administrator # ... end def clicks_the_big_button # ... end def see_a_picture # ... end def see_another_button # ... end |
What I like about this is that it is easy for developers to map a description to a method, and it separates the implementation of a Story from it’s definition. This allows the customers to work consistently to add and updates Story’s, as well as the same for developers.
Final Thoughts
One thing that lacks right now in the test/unit story runner is a way to mark Story’s as pending. I think this can be accomplished though by capitalizing the Story, Scenario or any of the story parts.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
Story "Logging in" SCENARIO "User with good credentials" do # this whole scenario is pending regardless of whats in it Given "..." When "..." end Scenario "User with bad credentials" do # this whole scenario is executed end STORY "Logging out" # marks the whole story as pending Scenario "logged in user" do # this will be marked as pending because of the story it belongs to end |
There has been recent discussion on the RSpec mailing list about this:
- http://rubyforge.org/pipermail/rspec-users/2007-October/003690.html
- http://rubyforge.org/pipermail/rspec-users/2007-October/003704.html
It seems that everyone is in agreement that the holy grail is a pure plain text file. There are drawbacks with this though that are currently being evaluated.
Pat Maddox has came up with a nice alternative to my above suggestion called SpecMatcher’s. It looks promising to the users of rspec though that Story Runner will turn into something truly beneficial to developers and customers alike.
Story Runner - constructive criticism
on October 15, 2007 @ 08:56 AM
If you keep up with RSpec development you’ll know that RBehave has been integrated into RSpec and is known as the “Story” Runner. This is a unfolding of current thoughts and criticism, I apologize for any lack of explanation, but I need to do a quick braindump.
I love the concept of Story Runner, but I do not like it’s current syntax. Below are the criticism’s for why. First though the code example I’ll use to discuss the Story syntax.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
Story "View Home Page", %{ As a user I want to view my home page So that I can get a birds eye view of the system }, :type => RailsStory do Scenario "Latest published article" do Given "an author named", "Zach" do |name| @user = User.create! :name => name end When "he visits the home page", "/" do |path| get path end Then "he should see the latest article published front and center" do # ... do something to see the article shows as expeted end end end |
Story Description
The story description is hideous. It requires a description, and then the story description, and then a type flag (at least for Rails projects). The Story itself should contain it’s actual story description. The pseudo description set in the first parameter and the :type flag should be able to be dropped. Right now these two things do not add value, but decrease customer readability.
Story Do/End Blocks
Everything is organized with do/end blocks. While I love the closure capabilities of ruby I am not a big fan of overusing blocks in Story files themselves. I would much rather drop the do/end blocks unless they provide needed clarity.
I’d like to remove the do/end block on Story because it the definition of the file format should read.. “All Scenarios belong to the preceding Story declaration”. Which to me is still just as readable.
Scenario Do/End Blocks
These should stay put. To me these are essential for providing clarity amongst your acceptance tests which scenario they are pertaining to.
Story Part Do/End Blocks
Story part (Given, When, Then, And) do/end blocks need to go away completely. They allow for developers to embed code directly into the high level story, which immediately reduces the readability from both a customer and developer perspective.
It has been mentioned that you can use editors code folding techniques to hide the code, but as pointed out on the rspec mailing list I don’t want my customer to have to use a code editor to read the acceptance tests.
Argument Passing
After every story part in the above example you have the ability to pass in arguments to the do/end block. When this adds value it makes sense to do this, but when it is a trivial piece of information it doesn’t seem to add any value. Instead it detracts readability.
It detracts readability by creating new tokens a customer has to visually parse, both in the argument list for the story part and also the argument list for the do/end block. It also makes data that may not be important seem important because they are singled out as their own arguments.
Argument passing should be used to add value to the story part with something that helps identify a behavior that is going to happen that your test is going to depend on. Usually this is not the user’s name or the root path (”/”) of a site, although in some cases it may be.
The Process Is Flawed
The ideal process is having a customer write and own the stories and the acceptance tests. As these change the customer should be responsible for updating them. The developers should be responsible for implementing them.
Given the above format once you add embedded code to a Story part you immediately reduce the readability from a customer’s perspective to own and maintain that Story and it’s acceptance tests should it change in the future. Also if a customer changes a Story should he/she be responsible for deleting the developers implementation of last acceptance test?
So the process is flawed. We shouldn’t have a format which doesn’t provide consistency to both the developer and the customer. So we need to tweak the Story format to enable a format which is consistent at both creation and change/update time of a Story and/or it’s acceptance tests.
Reusable Code
Embedding code inside a Story part renders it non-reusable. So to combat this you create a helper method and call from within the Story part’s do/end block. So now you have a nice clean description and with a do/end block wrapping a helper method, like below:
1 2 3 4 |
Given "a user logged into the system", "Joe" do |name| @user = User.create! name login_as @user end |
I see this and I want to refactor this. Clearly the description well named. I should be able to rely on a similarly well named helper method to handle creating or finding a user and logging that user in. If I do this then why do I need a do/end block (besides the fact of RSpec using it to trigger a pending Story)?
It seems so far that you don’t need a do/end block. It doesn’t add value. It takes away value.
form_test_helper 1.1.0 released!
on September 20, 2007 @ 12:22 AM
form_test_helper 1.1.0 has been released!
This update is for those who develop on Rails Edge. A recent update to Rails broke break how the tests run with form_test_helper.
So if you are on an Rails Edge revision of 7421 or higher then you should use form_test_helper trunk. The plugin repository URL is:
If you are on Rails Edge, but you’re not up to revision 7421 yet you will want to install and use form_test_helper-1.1.0. The plugin repository URL is:
If you are using Rails 1.2.x or a Rails Edge revision that is less then 6474 then you should use form_test_helper-1.0.0. The plugin repository URL is:
For more information please refer to the form_test_helper project page:
Not Testing Views, How Jay Tests
on September 18, 2007 @ 02:45 AM
Jay Fields mentions in his post How We Test that he doesn’t write view tests.
View tests, in my experience, aren’t necessary unless you are putting logic in your view. I prefer to keep the logic out of the view and ignore view tests entirely.
I agree with a lot of what Jay blogs about, but this I don’t think I do, but it’s hard to say because he didn’t post any context or information about his statement.
Although Jay has a point in keeping logic out of the view, view tests themselves are still an important aspect of testing rails applications. Here’s why I think you should test your views:
- Integration tests should be lightweight and very high level (customer readable or as close as you can get to it)
- If a customer wants information A, B and C to be on page foo then you need prove that A, B and C show up. Here you can use a view test! (An integration test would test going through the application, but view tests would test the details to make sure the right information is on the page.)
- Controller/functional tests should not test anything view related, so this requires a separate view test
- View tests may help keep your views organized and manageable
- View tests encourage the use of using helper objects/methods because you don’t want to write tests to test logic in the view. If you don’t test your views it’s easier to put logic in there.
The thing that makes me want to keep view tests are that, if a customer says I want to see this information, then it is my job to prove that it show’s up. There are three options for this:
- Put the testing of that information being displayed in your controller test. (this is painful!)
- Put the testing of that information being displayed in your integration test. (bloats your high level customer readable integration test. I want to avoid this bloat at this level!)
- Put the testing of that information in it’s own isolated view test (my preference of choice!)
YMMV based on your project. It may also vary based on your team setup and chemistry. On my current project the developers work with a HTML/CSS Builder to build the whole site. Several times we (our developers and HTML/CSS builder) have made pieces of information or links disappear when updating views. Without our view tests we wouldn’t have caught it as early on.
I have heard an argument against view testing which has to do with the cost of writing and maintaining view tests against the cost of letting developers, testers or customers find them. The argument is that “it’s cheaper to not write a view test and let someone find a bug rather then to write a view test and fix something before someone finds a bug”.
I disagree with this because I think there is a lot of risk involved with letting precious information slip through the cracks. Web applications these days often involve a lot of views and a lot of information. The whole point of test automation is to not require that someone remembers to test everything. Automated view tests are faster, they never forget a piece of important information to look for and they don’t require that anyone remembers everything that needs to be displayed.
There are ways to test your views which makes them feel unnecessary, brittle and painful, but this can be avoided. You can have easy, meaningful view tests which add value to your project for your development team and for your customer.
Mike Clark's - How Would You Test This
on September 18, 2007 @ 02:13 AM
Below is my rspec answer to Mike Clark’s recent post How Would You Test This which challenges people to post their own solution to how you’d test his MenuitemsController.
One thing Mike doesn’t mention about the frustration that people have with testing controllers is testing that testing controllers requires you to test your view associated with it (unless you are only redirecting).
There are ways around testing views, but most install a custom hack or installing a third party plugin or framework like rspec, Test::Rails or view_test.
Since Mike didn’t include any views in his original post I haven’t provided any tests for them in this post.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
require File.dirname(__FILE__) + '/../spec_helper' def do_post(attributes) post :create, :menu_item => attributes end describe MenuItemsController, 'Creating a new menu item (success)' do before do attributes = {'name' => "Enchilada", 'price' => 4.99} @menu_item = mock_model(MenuItem) MenuItem.should_receive(:new).with(attributes).once.and_return(@menu_item) @menu_item.should_receive(:save).with().once.and_return(true) do_post attributes end it 'redirects to index' do response.should redirect_to(menu_items_url) end it 'assigns @menu_item' do assigns[:menu_item].should be(@menu_item) end it 'sets the flash notice' do flash[:notice].should_not be(nil) end end describe MenuItemsController, 'Creating a new menu item (failure)' do before do attributes = {'name' => "Enchilada", 'price' => 4.99} @menu_item = mock_model(MenuItem) MenuItem.should_receive(:new).with(attributes).once.and_return(@menu_item) @menu_item.should_receive(:save).with().once.and_return(false) do_post attributes end it 'renders new template on failed save' do response.should be_success response.should render_template('new') end it "assigns @menu_item" do assigns[:menu_item].should be(@menu_item) end it "not set the flash notice" do flash[:notice].should be(nil) end end |
rspec's mocking framework is staying put
on September 05, 2007 @ 02:02 AM
On the rspec-users mailing list there’s been talk recently of removing the built-in mocking framework. The idea was that it offered nothing that the existing mocking frameworks like Mocha, Flexmock or Hardmock didn’t already offer.
The other day David Chelimsky announced in this post that it will be keeping rspec’s mocking framework for the foreseeable future.
form_test_helper on edge
on September 01, 2007 @ 11:28 PM
Well I’ve joined the Google Code project for form_test_helper . So form_test_helper will now work with Rails Edge, trunk revisions 6764 all the way up to 7393 (todays latest commit).
If you are using Rails 1.2.x or a Rails Edge revision less then 6764 then please use the 1.0.0 tag for form_test_helper, otherwise use what we consider form_test_helper trunk.
Installing for Rails Edge greater than or equal to 6764
script/plugin install http://form-test-helper.googlecode.com/svn/form_test_helper
Installing for Rails Edge less than 6764
script/plugin install http://form-test-helper.googlecode.com/svn/tags/form_test_helper-1.0.0
I am going to put these notes on the project home page as soon as I get permissions to make that update if Jason doesn’t make the change himself.
Enjoy form_test_helper on Edge!
form_test_helper for Rails Edge
on August 26, 2007 @ 04:46 AM
The wonderful plugin form_test_helper written by Jason Garber hasn’t worked with Rails Edge since this past spring. I monkey patched it to get it to work a few months ago, and tonight I submitted a patch which fixes form_test_helper with Rails Edge. The plugin has been tested to work with Rails Edge revisions 6764 to 7358.
The patch can be found here
http://www.continuousthinking.com/form_test_helper_edge.diff
I talked to Jason in July about submitting a patch and I believe it’ll be accepted and a new form_test_helper released, but in case you don’t want to wait please apply the patch yourself. You can do this by opening a terminal and following the below steps:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
$> cd RAILS_ROOT/vendor/plugins $> wget http://www.continuousthinking.com/form_test_helper_edge.diff $> cd form_test_helper $> patch -p0 < ../form_test_helper_edge.diff # you should now be able to run rake $> rake (in /Users/zdennis/source/opensource_projects/blah/vendor/plugins/form_... /opt/local/bin/ruby -Ilib:lib "/opt/local/lib/ruby/gems/1.8/... Loaded suite /opt/local/lib/ruby/gems/1.8/gems/rake-0.7.3/lib/rake/rake... Started ................................................................. Finished in 0.372041 seconds. 65 tests, 293 assertions, 0 failures, 0 errors |
Enjoy!

