Forum: RSpec Can I do foo.should (be_nil || be_empty) in rspec

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
85d99e7678d8720f6e00ab0f60fe6ea9?d=identicon&s=25 Andrew Premdas (Guest)
on 2008-11-04 12:12
(Received via mailing list)
Is there any way to do

  foo.should (be_nil || be_empty)

in rspec.

Thanks in advance
Be3698f145a80c1230fd667c87d0f0c8?d=identicon&s=25 Tom Stuart (Guest)
on 2008-11-04 12:23
(Received via mailing list)
On 4 Nov 2008, at 11:10, Andrew Premdas wrote:
> Is there any way to do
>   foo.should (be_nil || be_empty)
> in rspec.

"foo.should be_blank" would work if you're using Rails (i.e.
ActiveSupport is loaded).

Cheers,
-Tom
2ce9c0106b5851b2294ba5eb9f5c04bd?d=identicon&s=25 Ashley Moran (Guest)
on 2008-11-04 12:25
(Received via mailing list)
On 4 Nov 2008, at 11:10, Andrew Premdas wrote:

> Is there any way to do
>
>   foo.should (be_nil || be_empty)
>
> in rspec.

That won't do what you want it to, at first glance it will always
match with be_nil.  You could write a custom matcher
(be_nil_or_empty), but I suspect that's not the real answer here.

Why do you want to do this?  What is the distinction between nil and
empty in your app?  I suspect this is a data modelling issue rather
than a spec issue.  (Be very wary as soon as you see conditionals in
your code.)

Ashley


--
http://www.patchspace.co.uk/
http://aviewfromafar.net/
85d99e7678d8720f6e00ab0f60fe6ea9?d=identicon&s=25 Andrew Premdas (Guest)
on 2008-11-04 12:28
(Received via mailing list)
Sweet I'm using rails so will give it a go. Any ideas about the general
case, is making a custom matcher the (only) way to go?
All best

Andrew

2008/11/4 Tom Stuart <tom@experthuman.com>
2ce9c0106b5851b2294ba5eb9f5c04bd?d=identicon&s=25 Ashley Moran (Guest)
on 2008-11-04 12:57
(Received via mailing list)
On 4 Nov 2008, at 11:26, Andrew Premdas wrote:

> Any ideas about the general case, is making a custom matcher the
> (only) way to go?

Can you give an example of what you're doing, or think you might do?
Until I saw Tom's reply it never occurred to me that you might be
dealing with strings (I thought you were doing something with an array
or other collection.)

Ashley

--
http://www.patchspace.co.uk/
http://aviewfromafar.net/
85d99e7678d8720f6e00ab0f60fe6ea9?d=identicon&s=25 Andrew Premdas (Guest)
on 2008-11-04 13:47
(Received via mailing list)
General case I'm thinking about is just testing that something should be
one
thing or another
   e.g x.should be(foo || bar)

Haven't got a specific example at the moment apart from the blank one.
What
I'm thinking about is the syntax to say this in a spec, as I think there
must be lots of times when having this sort of syntax would be useful.

All best

Andrew



2008/11/4 Ashley Moran <ashley.moran@patchspace.co.uk>
2ce9c0106b5851b2294ba5eb9f5c04bd?d=identicon&s=25 Ashley Moran (Guest)
on 2008-11-04 14:59
(Received via mailing list)
On 4 Nov 2008, at 12:45, Andrew Premdas wrote:

> General case I'm thinking about is just testing that something
> should be one thing or another
>
>    e.g x.should be(foo || bar)
>
> Haven't got a specific example at the moment apart from the blank
> one.  What I'm thinking about is the syntax to say this in a spec,
> as I think there must be lots of times when having this sort of
> syntax would be useful.

Hi Andrew

I suspect that in general the concept of an object O being (foo ||
bar) actually means there's a rule that makes your object baz
instead.  The reason is that if you spec foo and bar independently,
you double the number of contexts for objects that depend on O.

So this might not look to bad:

   describe MyObject do
     before(:each) do
       @o = MyObject.new
     end

     it "should be foo or bar" do
       @o.should be_foo_or_bar
     end
   end

but it means everywhere else you're forced to duplicate that logic, eg:

   describe MyOtherObject do
     describe "when its MyObject is foo" do
       before(:each) do
         o = mock(MyObject, :foo => true, :bar => false)
         @oo = MyOtherObject.new(o)
       end
       it "should be faz" do
         @oo.should be_faz
       end
     end

     describe "when its MyObject is bar" do
       before(:each) do
         o = mock(MyObject, :foo => false, :bar => true)
         @oo = MyOtherObject.new(o)
       end
       it "should be faz" do
         @oo.should be_faz
       end
     end

     describe "when its MyObject is neither foo nor bar" do
       before(:each) do
         o = mock(MyObject, :foo => false, :bar => false)
         @oo = MyOtherObject.new(o)
       end
       it "should not be faz" do
         @oo.should_not be_faz
       end
     end
   end

instead of just:

   describe MyOtherObject do
     describe "when its MyObject is baz" do
       before(:each) do
         o = mock(MyObject, :baz => true)
         @oo = MyOtherObject.new(o)
       end
       it "should be faz" do
         @oo.should be_faz
       end
     end

     describe "when its MyObject is not baz" do
       before(:each) do
         o = mock(MyObject, :baz => false)
         @oo = MyOtherObject.new(o)
       end
       it "should not be faz" do
         @oo.should_not be_faz
       end
     end
   end

s/foo/nil/
s/bar/empty/
s/baz/blank/

This make sense?  Sorry if it's a bit abstract, or has typos.  I
didn't actually run that code, of course...

I think in summary, two branches in your specs => you are violating
Tell Don't Ask (somewhere else) in your code.

Ashley

--
http://www.patchspace.co.uk/
http://aviewfromafar.net/
42172acdf3c6046f84d644cb0b94642c?d=identicon&s=25 Pat Maddox (pergesu)
on 2008-11-04 16:32
(Received via mailing list)
"Andrew Premdas" <apremdas@gmail.com> writes:

> General case I'm thinking about is just testing that something should be one thing or 
another
>
>    e.g x.should be(foo || bar)
>
> Haven't got a specific example at the moment apart from the blank one.  What I'm 
thinking about is the syntax to say this in a spec, as I
> think there must be lots of times when having this sort of syntax would be useful.

Hi,

This is a case where a custom matcher would be hiding a concept that
belongs directly in your code.  If you really don't care about the
difference between empty and nil, you should create a method - such as
#blank? - that handles that for you.

Pat
85d99e7678d8720f6e00ab0f60fe6ea9?d=identicon&s=25 Andrew Premdas (Guest)
on 2008-11-04 17:23
(Received via mailing list)
Ashley,
Thanks for your time on this, the reply does make sense, and I can see
from
an OO point of view that any particular object being (foo||bar) is
equivalent to that object being baz. However with the dynamic nature of
ruby
we often don't know what object we are going to be dealing with in our
tests/specs. Whilst a unit test will generally (always?) be aimed at a
particular type, when implementing a plain text feature/story we are
often
working at a much higher level. In these cases the (foo || bar)
construct
could mean different types and a baz might not exist or be particularly
easy
to represent or formulate.

I can see that wanting this construct, could indicate a smell maybe a
badly
worded story - i.e. a conjunction step.

All best

Andrew

2008/11/4 Ashley Moran <ashley.moran@patchspace.co.uk>
85d99e7678d8720f6e00ab0f60fe6ea9?d=identicon&s=25 Andrew Premdas (Guest)
on 2008-11-04 17:42
(Received via mailing list)
Ok I see. I was approaching this more from the syntax that my stories
can
express rather than what my code does. However from these replies and a
re-read of the cucumber wiki I can see that any step that requires the
(foo||bar) construct is by definition a conjunction and can be broken
into
smaller steps.
However we only have 'And' available in stories, do we need 'Or'?

All best

Andrew

2008/11/4 Pat Maddox <pergesu@gmail.com>
F86901feca747abbb5c6c020362ef2e7?d=identicon&s=25 Zach Dennis (zdennis)
on 2008-11-04 17:46
(Received via mailing list)
On Tue, Nov 4, 2008 at 11:36 AM, Andrew Premdas <apremdas@gmail.com>
wrote:
> Ok I see. I was approaching this more from the syntax that my stories can
> express rather than what my code does. However from these replies and a
> re-read of the cucumber wiki I can see that any step that requires the
> (foo||bar) construct is by definition a conjunction and can be broken into
> smaller steps.
> However we only have 'And' available in stories, do we need 'Or'?

What is your scenario that you are thinking of using an "or" ? This
may be helpful, otherwise we're going to speculating about the
theoretical use cases. I'd rather focus on your specific use case. :)

--
Zach Dennis
http://www.continuousthinking.com
http://www.mutuallyhuman.com
85d99e7678d8720f6e00ab0f60fe6ea9?d=identicon&s=25 Andrew Premdas (Guest)
on 2008-11-04 17:59
(Received via mailing list)
Oh I was definitely into theoretical speculation here :) - haven't got a
particular case at the moment

2008/11/4 Zach Dennis <zach.dennis@gmail.com>
5d38ab152e1e3e219512a9859fcd93af?d=identicon&s=25 David Chelimsky (Guest)
on 2008-11-04 18:16
(Received via mailing list)
On Tue, Nov 4, 2008 at 9:29 AM, Pat Maddox <pergesu@gmail.com> wrote:
>
> This is a case where a custom matcher would be hiding a concept that
> belongs directly in your code.  If you really don't care about the
> difference between empty and nil, you should create a method - such as
> #blank? - that handles that for you.

In which case you would get be_blank for free, in case you weren't
aware.

FYI - if you REALLY want to match against either, it's pretty easy to
do w/ simple matcher:

def be_nil_or_empty
  simple_matcher "nil? or empty? to return true" do |actual|
    actual.nil? || actual.empty?
  end
end

Cheers,
David
2ce9c0106b5851b2294ba5eb9f5c04bd?d=identicon&s=25 Ashley Moran (Guest)
on 2008-11-04 20:17
(Received via mailing list)
On Nov 04, 2008, at 5:07 pm, David Chelimsky wrote:

> FYI - if you REALLY want to match against either, it's pretty easy to
> do w/ simple matcher:
>
> def be_nil_or_empty
>  simple_matcher "nil? or empty? to return true" do |actual|
>    actual.nil? || actual.empty?
>  end
> end


Wow, I completely forgot about simple_matcher.  That REALLY deserves a
more prominent place in the docs!  It's a great feature.

Would be really cool if you could do it like this though:

  simple_matcher :be_nil_or_empty, "nil? or empty? to return true" do |
actual|
    actual.nil? || actual.empty?
  end

and have it call define_method for you.

That's one I could hopefully do myself in time, after I've got a few
Merb/DataMapper jobs out of the way.

WYDAT?  Worth filing a ticket for?

Ashley

--
http://www.patchspace.co.uk/
http://aviewfromafar.net/
5d38ab152e1e3e219512a9859fcd93af?d=identicon&s=25 David Chelimsky (Guest)
on 2008-11-04 20:28
(Received via mailing list)
On Tue, Nov 4, 2008 at 1:14 PM, Ashley Moran
<ashley.moran@patchspace.co.uk> wrote:
>> end
>  end
>
> and have it call define_method for you.
>
> That's one I could hopefully do myself in time, after I've got a few
> Merb/DataMapper jobs out of the way.
>
> WYDAT?  Worth filing a ticket for?

If you can do it w/o breaking existing behaviour, sure.

Alternatively, you could add a new method:

def_matcher

or something like that.

Either way, it would be totally worth it.
F86901feca747abbb5c6c020362ef2e7?d=identicon&s=25 Zach Dennis (zdennis)
on 2008-11-04 20:33
(Received via mailing list)
On Tue, Nov 4, 2008 at 2:14 PM, Ashley Moran
<ashley.moran@patchspace.co.uk> wrote:
>> end
>  end
>
> and have it call define_method for you.
>
> That's one I could hopefully do myself in time, after I've got a few
> Merb/DataMapper jobs out of the way.
>
> WYDAT?  Worth filing a ticket for?

There are a few obstacles that it would have to overcome. As-is I
don't think that will work. If you file a ticket I'll comment there as
to why I think that. :)


--
Zach Dennis
http://www.continuousthinking.com
http://www.mutuallyhuman.com
42172acdf3c6046f84d644cb0b94642c?d=identicon&s=25 Pat Maddox (pergesu)
on 2008-11-04 20:49
(Received via mailing list)
"David Chelimsky" <dchelimsky@gmail.com> writes:

> Alternatively, you could add a new method:
>
> def_matcher

I dig this.

Pat
5d38ab152e1e3e219512a9859fcd93af?d=identicon&s=25 David Chelimsky (Guest)
on 2008-11-04 20:56
(Received via mailing list)
On Tue, Nov 4, 2008 at 1:47 PM, Pat Maddox <pergesu@gmail.com> wrote:
> "David Chelimsky" <dchelimsky@gmail.com> writes:
>
>> Alternatively, you could add a new method:
>>
>> def_matcher
>
> I dig this.

FYI - I was talking off-line (on line, really, but outside this list)
to wycats and he's got some matcher stuff in merb that I, shamefully,
have yet to check out in detail. It'd be good to peak at that and see
if it makes sense to bring it into rspec, or maybe release it as a
plugin/extension.
2ce9c0106b5851b2294ba5eb9f5c04bd?d=identicon&s=25 Ashley Moran (Guest)
on 2008-11-04 21:43
(Received via mailing list)
On Nov 04, 2008, at 7:24 pm, Zach Dennis wrote:

> There are a few obstacles that it would have to overcome. As-is I
> don't think that will work. If you file a ticket I'll comment there as
> to why I think that. :)


I've filed a ticket[1].  Unleash your scepticism, Zach! :)

Ashley


[1]
http://rspec.lighthouseapp.com/projects/5645-rspec...

--
http://www.patchspace.co.uk/
http://aviewfromafar.net/
This topic is locked and can not be replied to.