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:
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:
sudo gem install remarkable_rails
You can also install just remarkable or just remarkable_activerecord. But remarkable_rails brings you the whole packet.
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:
In Remarkable, we can have the same results in Portuguese:
Usuário
- deve exigir presença de nome e email
- deve garantir tamanho de nome seja entre 3..40 caracteres
- deve garantir valores únicos para email
- deve aceitar apenas números em idade permitindo somente valores inteiros e permitindo valores nulos
As you have noticed everything gets translated including the class and attributes names. This happens by setting up Remarkable and Rails yml files.
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.
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:
it "should have one manager" do
pending("create managers resource")
end
it "should validate associated manager" do
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.
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.
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")
There is a presentation from José Valim that explains this feature with more details, but it basically makes your controllers specs from this:
describe TasksController do
def mock_task(stubs={})
@task ||= mock_model(Task, stubs)
end
describe "responding to #POST create" do
it "exposes a newly created task as @task" do
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
it "redirects to the created task" do
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:
describe TasksController do
mock_models :task
describe :post => :create, :task => {:these => 'params'} do
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. :)
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)
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.
Parabéns, excelente trabalho!
Spam?
Olá Carlos,
Tive uma dúvida, o Remarkable é compatível com o Cucumber?
[]`s
Rodrigo
Totalmente, Rodrigo!
Hi Carlos,
This is a very interesting post. I had just heard about Remarkable. Your article just convinced me! It looks so easy and so DRY. I’ll probably adopt it.
Thanks a lot
Wow. Remarkable is amazing. Thanks so much. I already missed the macros from Should in Rspec, but you made my day. Good work.