New RSpec methods to Object proposal: should_all and should_none

I was thinking that it would be great to add 2 additional methods to
Object: should_all and should_none.

The idea is that we would be able to write tests like:

[@admin, @allowed_user].should_all be_allowed_to_visit(url)

[@unprivileged, @non_welcome].should_none be_allowed_to_visit(url)

Implementation is trivial, but I think that tests would become much
cleaner than:

[@admin, @allowed_user].each{|u| u.should be_allowed_to_visit(url)}

Any thoughts on that?

Rodrigo.


Faça ligações para outros computadores com o novo Yahoo! Messenger

On Wed, Dec 9, 2009 at 5:41 AM, Rodrigo Rosenfeld R. <
[email protected]> wrote:

than:

[@admin, @allowed_user].each{|u| u.should be_allowed_to_visit(url)}

Any thoughts on that?

How about:

each_of(@admin, @allowed_user).should be_allowed_to_visit(url)
none_of(@admin, @allowed_user).should be_allowed_to_visit(url)

This gets the cleanliness without adding to Object.

WDYT?

David

[@admin, @allowed_user].should all(be_allowed_to_visit(url))
[@admin, @allowed_user].should all_be_allowed_to_visit(url)

I prefer the first so as not to introduce more “magic” but if it catches
on then moving to the second might be worthwhile.

Pat

On Wed, Dec 9, 2009 at 11:55 AM, Pat M. [email protected]
wrote:

[@admin, @allowed_user].should all(be_allowed_to_visit(url))
[@admin, @allowed_user].should all_be_allowed_to_visit(url)
I prefer the first so as not to introduce more “magic” but if it catches on
then moving to the second might be worthwhile.

Seems like there are a few approaches to syntax that might work, but
we also have to consider failure messages. Either of Pat’s suggestions
would make it easier to provide a meaningful failure message.
Something like:

Expected <#User @role => ‘admin’>, <#User @role => ‘allowed’> to be
allowed to visit /some/path:

  • <#User @role => ‘allowed’> was not
  • <#User @role => ‘admin’> was

I’d like to see this developed outside rspec first, let a few ppl play
w/ different approaches. Once the idea has been fleshed out and in use
we can merge in the one that gets community consensus - or not :slight_smile:

Cheers,
David

El 09/12/2009, a las 19:15, David C.
escribió:

On Wed, Dec 9, 2009 at 11:55 AM, Pat M. <[email protected]

wrote:
[@admin, @allowed_user].should all(be_allowed_to_visit(url))
[@admin, @allowed_user].should all_be_allowed_to_visit(url)

[@admin, @allowed_user].should_all be_allowed_to_visit(url)
How about:
each_of(@admin, @allowed_user).should be_allowed_to_visit(url)
none_of(@admin, @allowed_user).should be_allowed_to_visit(url)
This gets the cleanliness without adding to Object.

I’m puzzled as to why people are so focussed on making specs read like
plain text English when they are still developer-facing Ruby code.

Especially suprised in this case of wanting to avoid the “each +
block” enumeration idiom, which is about as “bread and butter” Ruby as
you can get, readable to anybody who’s ever read the first chapter of
a Ruby book.

Cheers,
Wincent

On Wed, Dec 9, 2009 at 2:16 PM, Wincent C. [email protected]
wrote:

[email protected] wrote:

Implementation is trivial, but I think that tests would become much

I’m puzzled as to why people are so focussed on making specs read like plain
text English when they are still developer-facing Ruby code.

Especially suprised in this case of wanting to avoid the “each + block”
enumeration idiom, which is about as “bread and butter” Ruby as you can get,
readable to anybody who’s ever read the first chapter of a Ruby book.

I think that the english text is secondary to doing something which
doesn’t require mixing another method or methods into all objects.

In the early days RSpec added quite a few more methods to Object
besides (or perhaps instead of) should and should_not. One of the
goals is to minimize disturbing the system being speced.


Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale

On 9 Dec 2009, at 19:16, Wincent C. wrote:

Implementation is trivial, but I think that tests would become much

I’m puzzled as to why people are so focussed on making specs read
like plain text English when they are still developer-facing Ruby
code.

Especially suprised in this case of wanting to avoid the “each +
block” enumeration idiom, which is about as “bread and butter” Ruby
as you can get, readable to anybody who’s ever read the first
chapter of a Ruby book.

+1

Personally I’d use Cucumber for testing this sort of behaviour, but if
I was using RSpec for some reason, I’d be inclined to use macros so I
got a separate failing example for each type of user:

url = ‘http://some/url
[:admin, :allowed_user].each do |user_type|
it “should allow an #{user_type} to visit #{url}” do
user = instance_variable_get("@#{user_type}.to_sym)
user.should be_allowed_to_visit(url)
end
end

Either that or just simply a separate nested describe block for each
type of user:

describe “an admin user” do
before(:each) do
@user = Factory(:user, :admin => true)
end

it “should be allowed to access the URL”
end

etc.

cheers,
Matt

+447974 430184

Wincent C. [email protected] on 2009-12-09 at 13:39:

cleaner than:
I’m puzzled as to why people are so focussed on making specs read like
plain text English when they are still developer-facing Ruby code.

Especially suprised in this case of wanting to avoid the “each + block”
enumeration idiom, which is about as “bread and butter” Ruby as you can
get, readable to anybody who’s ever read the first chapter of a Ruby book.

For me the benefit would be clearer error messages on failures, because
of the potential to continue execution through the entirety of the
collection of inputs, rather than bailing on the first failed ‘should’.

This allowing a developer to diagnose classes of problems with the
collection rather than seeing failures one-by-one.

Compare the following two options:

[:foo, :bar, :baz, :qux].each { |x| x.should ==(:qux) }
<run 01> “Expected :foo to equal :qux”
(…fix :foo…)
<run 02> “Expected :bar to equal :qux”
(…fix :bar…)
<run 03> “Expected :baz to equal :qux”
(…realize the real problem is in dependent code that
affects all of foo bar and baz, and fix that…)
<run 04> PASS

each_of(:foo, :bar, :baz, :qux).should ==(:qux)
<run 01> “Expected each of :foo, :bar, :baz, :qux to equal :qux, but
:foo, :bar, :baz did not.”
(…fix dependent code that affects all of foo bar and
baz…)
<run 02> PASS

I look forward to continuing this discussion.

Cheers,

Paul

Paul H. escreveu:

On Dec 9, 2009, at 5:27 AM, David C. wrote:

each_of(@admin, @allowed_user).should be_allowed_to_visit(url)

<run 01> “Expected :foo to equal :qux”
:foo, :bar, :baz did not."
(…fix dependent code that affects all of foo bar and
baz…)
<run 02> PASS

I’ve read all the proposed syntax and I really like them all.
I don’t think the syntax below is as clear as the others proposed but I
understand that it may help improving the failure message:

[@admin, @allowed_user].should all(be_allowed_to_visit(url))

The syntax each_of/none_of is the clearer to me.

The point for the tests to read like English sentences is that it easies
test reading. Of course programmers will understand the statement using
Ruby. But when you have tons of tests to read, this kind of improvement
can make tests easier to be read, even by non-technical users when using
XP techniques for instance if you try to pair-reading the tests to see
if both programmer and client are expecting the same results…

Also, the Java community is experiencing the use of JRuby and RSpec to
test their Java applications and maybe they would prefer the
“should_all/should all” syntax.

I don’t like Cucumber, for instance, because I would take much more time
to write the stories from what I take writing the tests directly in
RSpec. And I personally find specs as simple to read as Cucumber
stories. But let’s not get on this discussion, please…

The point that the spec doesn’t need to stop in the first error from the
collection items is also a good one.

There is also another point. Some failure messages don’t mention the
object being tested. In that case, the error message may be unclear
because one won’t know which of the tested items caused the error when
using an “each” constructor.

Anyway, it is not a serious limitation of Rspec since it is trivial to
write such solutions if we want in our test suite. I can certainly leave
without these extensions, but I think that if they get into Rspec core,
it would be standardized among different projects and probably better
documented, which makes it easier to integrate a new team member.

Thank you for your proposals.

Best regards,

Rodrigo.


Faça ligações para outros computadores com o novo Yahoo! Messenger

On Wed, Dec 9, 2009 at 1:15 PM, David C. [email protected]
wrote:

Expected <#User @role => ‘admin’>, <#User @role => ‘allowed’> to be
allowed to visit /some/path:

  • <#User @role => ‘allowed’> was not
  • <#User @role => ‘admin’> was

I like Pat’s idea too, but

[x, y, z].should_not all_be_allowed_to(…)

doesn’t seem to be the same thing as

none_of(x, y, z).should be_allowed_to(…)

maybe
[x, y, z].should all_not_be_alllowed_to(…)

but I’m not sure


Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale

Rick DeNatale escreveu:

we also have to consider failure messages. Either of Pat’s suggestions

I was just thinking about that. Maybe “all” should be documented as in
“have_at_least”:
“should have_at_least(number).items
Warning: should_not have_at_least is not supported”

The correct way should be:

@collection.should none(be_allowed_to(…))

Of course the “none_of” syntax would be easier to read, but the option
above is also acceptable in my opinion…

Rodrigo.


Faça ligações para outros computadores com o novo Yahoo! Messenger