Wow, a major release? Yes, a major release and we have plenty reasons for that. Since me and José Valim were working on it for a couple months, we have quite a list :). So follow up:
1. Remarkable Core
Remarkable is now a framework for rspec matchers. Since Rails matchers are not simple, as Remarkable grew, we saw our matchers full of logic to show messages (description and failure messages) and that some methods could be automatically generated, reducing repetitive work.
Compare the allow_mass_assignment_of matcher in Remarkable 2.x and in Remarkable 3.0. Which one do you prefer? :)
So we built a DSL and called it Remarkable, which with Remarkable ActiveRecord and Remarkable Rails, provides you nice matchers/macros to speed up your tests. To install them, just do:
You can also install just remarkable or just remarkable_activerecord. But remarkable_rails brings you the whole packet.
2. I18n
On Rails Summit Latin America, Obie Fernandez talked about the Hash Rocket way and one of the items were that they actually print out the specs and give it to the client. Both me and José work with Rails projects and we couldn’t deliver the same to technical clients, because the output was in english. Well, we scratched our own itch!
This is how an English output would be like:
User
- should require name and email to be set
- should ensure length of name is within 3..40 characters
- should require unique values for email
- should ensure numericality of age allowing only integer values and allowing blank values
In Remarkable, we can have the same results in Portuguese:
As you have noticed everything gets translated including the class and attributes names. This happens by setting up Remarkable and Rails yml files.
3. Macros
In Remarkable earlier versions, we coded the matcher (validate_presence_of) but most of the time we had to do some tweaks in other to a matcher becomes a macro (should_validate_presence_of). In Remarkable 3.0 it happens transparently.
In other words, if you are using Remarkable 3.0 to build your matchers you have cleaner matchers, I18n support and transparent macros creation.
4. Pending and disabled macros
In Remarkable 2.2, we added the ability to mark macros as disabled:
xshould_validate_uniqueness_of :name
And it would print on your specs output:
As some people pointed out, Remarkable was still lacking support for pending macros. Pending examples in Rspec would be:
pending("create managers resource")
end
pending("create managers resource")
end
And now in Remarkable, you have the pending group:
pending "create managers resource" do
should_have_one :manager
should_validate_associated :manager
end
In both cases a message “PENDING: create managers resources” is appended to matcher description.
5. More options to matchers
In Remarkable 2.2, we started to support ALL Active Record validations with ALL options. And now we extended support for association matchers!
From only :dependent and :through as supported options, now it accepts:
Besides matchers became much smarter. Whenever :join_table or :through is given as option, it also checks if the given table exists. Whenever :foreign_key or :counter_cache is given, it also checks if the given column exists.
6. Controllers matchers extended
To provide I18n, we ported redirect_to and render_template matchers from rspec-rails. We also added some extra options to respond_with and render template, so you can now do:
render_template 'edit', :layout => 'users'
respond_with 422, :content_type => Mime::XML,
:body => /Unprocessable Entitity/
And the route matcher is willing to make your life twice easier. Since it tests params recognitation and routes generation at once, you can cut your routing_specs at least in a half! So the following lines:
route_for(:controller => "companies",
:action => "show",
:id => "1").should == "/companies/1"
params_from(:get, "/companies/1").should == {:controller => "companies",
:action => "show",
:id => "1" }
Will become:
route(:get, "/companies/1", :controller => "companies",
:action => "show",
:id => "1")
7. Macro stubs
There is a presentation from José Valim that explains this feature with more details, but it basically makes your controllers specs from this:
@task ||= mock_model(Task, stubs)
end
Task.should_receive(:new).with({'these' => 'params'}).
and_return(mock_task(:save => true))
post :create, :task => {:these => 'params'}
assigns[:task].should equal(mock_task)
end
Task.stub!(:new).and_return(mock_task(:save => true))
post :create, :task => {}
response.should redirect_to(task_url(mock_task))
end
end
end
Become this:
mock_models :task
expects :new, :on => Task, :with => {:these => 'params' }, :returns => mock_task
expects :save, :on => mock_task, :returns => true
should_assign_to :task, :with => mock_task
should_redirect_to {task_url(mock_task) }
end
end
It aims to improve readability and be more DRY, since you declare your expectations/stubs just once. You can see the whole controller specs in rspec and remarkable way compared here.
It works by eval’ing the expectation/stubs chain and performing the action before each macro is executed. On should_assign_to it evals using expectations (:should_receive), on should_redirect_to it uses stubs (:stub!).
We also want to thank David Chelimsky that gave the nice hint to allow :post => :create inside the describe method and suggested to use mocha syntax. :)
8. Documentation, documentation and documentation
Yes, three times, because each project is very well documented. Browse them:
Remarkable: http://remarkable.rubyforge.org/core/
Remarkable ActiveRecord: http://remarkable.rubyforge.org/activerecord/ http://remarkable.rubyforge.org/activerecord/classes/Remarkable/ActiveRecord/Matchers.html (just matchers)
Remarkable Rails: http://remarkable.rubyforge.org/rails/ http://remarkable.rubyforge.org/rails/classes/Remarkable/ActionController/Matchers.html (just matchers)
9. Volunteers?
Last but definitely not least: we need you!

We created a solid basis for matchers/macros creation. And we want to take it further by hosting even more matchers. So anyone who wants to work on Remarkable Datamapper, Remarkable Sequel, Remarkable Sinatra, please step in! We are waiting for you. :)
And all the others can equally help us by joining the group and posting bugs, matchers, enhancements in bug tracking system.