I'm trying to create a custom matcher for my tests in RoR using RSpec.
define :be_accessible do |attributes|
attributes = attributes.is_a?(Array) ? attributes : [attributes]
attributes.each do |attribute|
match do |response|
response.class.accessible_attributes.include?(attribute)
end
description { "#{attribute} should be accessible" }
failure_message_for_should { "#{attribute} should be accessible" }
failure_message_for_should_not { "#{attribute} should not be accessible" }
end
end
I want to be able to write something like the following in my tests:
...
should be_accessible(:name, :surname, :description)
...
but with the matcher defined above, I must pass an array of symbols instead of symbols separated by commas otherwise the test examines only the first symbol.
Any ideas?
RSpec is a testing tool for Ruby, created for behavior-driven development (BDD). It is the most frequently used testing library for Ruby in production applications. Even though it has a very rich and powerful DSL (domain-specific language), at its core it is a simple tool which you can start using rather quickly.
RSpec is a Behavior-Driven Development tool for Ruby programmers. BDD is an approach to software development that combines Test-Driven Development, Domain Driven Design and Acceptance Test-Driven Planning. RSpec helps you do the TDD part of that equation, focusing on the documentation and design aspects of TDD.
RSpec is a unit test framework for the Ruby programming language. RSpec is different than traditional xUnit frameworks like JUnit because RSpec is a Behavior driven development tool.
RSpec is a framework that allows us to do that. The "R" stands for Ruby, and "Spec" is short for Specification. A specification is a detailed requirement that our code should meet. Or more formally, it's an executable example that tests whether a portion of code exhibits the expected behavior in a controlled context.
I made it work this way :
RSpec::Matchers.define :be_accessible do |*attributes|
match do |response|
description { "#{attributes.inspect} be accessible" }
attributes.each do |attribute|
failure_message_for_should { "#{attribute} should be accessible" }
failure_message_for_should_not { "#{attribute} should not be accessible" }
break false unless response.class.accessible_attributes.include?(attribute)
end
end
end
I inverted the match
and the each
loop. I think this is the way Rspec expect it to be, as the block given to the match
method is the one executed by Rspec abstract matcher (I guess).
By defining the block with |*attributes|
, it takes the list of parameters and turn it into an Array
.
So calling should be_accessible(:name, :surname, :description)
will work.
By the way, if you just want to check for the existence of attributes, a simple
should respond_to(:name, :surname, :description)
works as well. But it does not looks like for mass-assignement aspect.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With