Hi all, I''m spec''ing a method that yields a value. Right now, I spec it like this: result = nil thing.do_stuff { |value| result = value } result.should == expected This feels like too much ceremony. What I want to do is something more this: thing.do_stuff.should yield_value(expected) Is there anything built into RSpec to let me do this? If not, how do other people test yields? cheers, Matt -- Freelance programmer & coach Author, http://pragprog.com/book/hwcuc/the-cucumber-book Founder, http://www.relishapp.com/ Twitter, https://twitter.com/mattwynne -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20120307/0e99e217/attachment.html>
How about this? thing.do_stuff(&:to_s).should == expected Best regards Morten M?ller Riis On Mar 7, 2012, at 8:22 AM, Matt Wynne wrote:> Hi all, > > I''m spec''ing a method that yields a value. Right now, I spec it like this: > > result = nil > thing.do_stuff { |value| result = value } > result.should == expected > > This feels like too much ceremony. What I want to do is something more this: > > thing.do_stuff.should yield_value(expected) > > Is there anything built into RSpec to let me do this? If not, how do other people test yields? > > cheers, > Matt > > -- > Freelance programmer & coach > Author, http://pragprog.com/book/hwcuc/the-cucumber-book > Founder, http://www.relishapp.com/ > Twitter, https://twitter.com/mattwynne > > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20120307/ddfb2f84/attachment.html>
Hi Matt, On Wed, Mar 7, 2012 at 2:22 AM, Matt Wynne <matt at mattwynne.net> wrote:> Hi all, > > I''m spec''ing a method that yields a value. Right now, I spec it like this: > > result = nil > thing.do_stuff { |value| result = value } > result.should == expected > > This feels like too much ceremony. What I want to do is something more > this: > > thing.do_stuff.should yield_value(expected) > > Is there anything built into RSpec to let me do this? If not, how do other > people test yields? > >I came across this about a month or two ago. You can do this: thing.should_receive(:do_stuff).and_yield( whatever) See http://rubydoc.info/gems/rspec-mocks/frames for more details. Regards, Ken -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20120307/3b39dab9/attachment-0001.html>
On 7 Mar 2012, at 15:12, Ken Chien wrote:> Hi Matt, > On Wed, Mar 7, 2012 at 2:22 AM, Matt Wynne <matt at mattwynne.net> wrote: > Hi all, > > I''m spec''ing a method that yields a value. Right now, I spec it like this: > > result = nil > thing.do_stuff { |value| result = value } > result.should == expected > > This feels like too much ceremony. What I want to do is something more this: > > thing.do_stuff.should yield_value(expected) > > Is there anything built into RSpec to let me do this? If not, how do other people test yields? > > > I came across this about a month or two ago. > You can do this: > thing.should_receive(:do_stuff).and_yield( whatever)Surely that sets up a mocked collaborator to respond by yielding something, doesn''t it? That''s not what I''m looking for. I want to specify that a method on the class I''m testing yields a certain value. cheers, Matt -- Freelance programmer & coach Author, http://pragprog.com/book/hwcuc/the-cucumber-book Founder, http://www.relishapp.com/ Twitter, https://twitter.com/mattwynne -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20120307/df1922ef/attachment.html>
On 7 Mar 2012, at 11:39, Morten M?ller Riis wrote:> On Mar 7, 2012, at 8:22 AM, Matt Wynne wrote: > >> Hi all, >> >> I''m spec''ing a method that yields a value. Right now, I spec it like this: >> >> result = nil >> thing.do_stuff { |value| result = value } >> result.should == expected >> >> This feels like too much ceremony. What I want to do is something more this: >> >> thing.do_stuff.should yield_value(expected) >> >> Is there anything built into RSpec to let me do this? If not, how do other people test yields? >> >> cheers, >> Matt> How about this? > > thing.do_stuff(&:to_s).should == expectedYes, that''s a neat hack, but I''d prefer to be able to assert on the actual yielded value, instead of the result of calling an arbitrary method on it. Doesn''t anyone else do this? cheers, Matt -- Freelance programmer & coach Author, http://pragprog.com/book/hwcuc/the-cucumber-book Founder, http://www.relishapp.com/ Twitter, https://twitter.com/mattwynne -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20120307/9b2fa1d5/attachment.html>
On Wed, Mar 7, 2012 at 11:56 AM, Matt Wynne <matt at mattwynne.net> wrote:> > On 7 Mar 2012, at 11:39, Morten M?ller Riis wrote: > > On Mar 7, 2012, at 8:22 AM, Matt Wynne wrote: > > > Hi all, > > I''m spec''ing a method that yields a value. Right now, I spec it like this: > > ? ? result = nil > ? ? thing.do_stuff { |value| result = value } > ? ? result.should == expected > > This feels like too much ceremony. What I want to do is something more this: > > ? ?thing.do_stuff.should yield_value(expected) > > Is there anything built into RSpec to let me do this? If not, how do other > people test yields? > > cheers, > Matt > > > How about this? > > thing.do_stuff(&:to_s).should == expected > > > Yes, that''s a neat hack, but I''d prefer to be able to assert on the actual > yielded value, instead of the result of calling an arbitrary method on it.thing.do_stuff(&:self) would be a bit less arbitrary :)> > Doesn''t anyone else do this? > > cheers, > Matt > > -- > Freelance programmer &?coach > Author,?http://pragprog.com/book/hwcuc/the-cucumber-book > Founder,?http://www.relishapp.com/ > Twitter,?https://twitter.com/mattwynne > > > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users
Matt, I have typically done what you are already doing, but I am also interested in the answer you seek. Another idea might be something like since #do-stuff would need to be invoked with a block: expect(thing, :do_stuff).to_yield val Zach On Wed, Mar 7, 2012 at 12:56 PM, Matt Wynne <matt at mattwynne.net> wrote:> > On 7 Mar 2012, at 11:39, Morten M?ller Riis wrote: > > On Mar 7, 2012, at 8:22 AM, Matt Wynne wrote: > > > Hi all, > > I''m spec''ing a method that yields a value. Right now, I spec it like this: > > ? ? result = nil > ? ? thing.do_stuff { |value| result = value } > ? ? result.should == expected > > This feels like too much ceremony. What I want to do is something more this: > > ? ?thing.do_stuff.should yield_value(expected) > > Is there anything built into RSpec to let me do this? If not, how do other > people test yields? > > cheers, > Matt > > > How about this? > > thing.do_stuff(&:to_s).should == expected > > > Yes, that''s a neat hack, but I''d prefer to be able to assert on the actual > yielded value, instead of the result of calling an arbitrary method on it. > > Doesn''t anyone else do this? > > cheers, > Matt > > -- > Freelance programmer &?coach > Author,?http://pragprog.com/book/hwcuc/the-cucumber-book > Founder,?http://www.relishapp.com/ > Twitter,?https://twitter.com/mattwynne > > > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users-- -- @zachdennis http://www.continuousthinking.com http://www.mutuallyhuman.com
On Wed, Mar 7, 2012 at 11:53 AM, Matt Wynne <matt at mattwynne.net> wrote:> > On 7 Mar 2012, at 15:12, Ken Chien wrote: > > Hi Matt, > On Wed, Mar 7, 2012 at 2:22 AM, Matt Wynne <matt at mattwynne.net> wrote: >> >> Hi all, >> >> I''m spec''ing a method that yields a value. Right now, I spec it like this: >> >> ? ? result = nil >> ? ? thing.do_stuff { |value| result = value } >> ? ? result.should == expected >> >> This feels like too much ceremony. What I want to do is something more >> this: >> >> ? ?thing.do_stuff.should yield_value(expected) >> >> Is there anything built into RSpec to let me do this? If not, how do other >> people test yields? >> > > I came across this about a month or two ago. > You can do this: > ??? thing.should_receive(:do_stuff).and_yield( whatever) > > > Surely that sets up a mocked collaborator to respond by yielding something, doesn''t it?Right.> That''s not what I''m looking for.Right again.> I want to specify that a method on the class I''m testing yields a certain value. > > cheers, > Matt > > -- > Freelance programmer &?coach > Author,?http://pragprog.com/book/hwcuc/the-cucumber-book > Founder,?http://www.relishapp.com/ > Twitter,?https://twitter.com/mattwynne > > > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users
On 7 Mar 2012, at 18:26, Zach Dennis wrote:> Matt, > > I have typically done what you are already doing, but I am also > interested in the answer you seek. Another idea might be something > like since #do-stuff would need to be invoked with a block: > > expect(thing, :do_stuff).to_yield valYeah, I like that. Is that real yet or is this just an idea?> > Zach > > On Wed, Mar 7, 2012 at 12:56 PM, Matt Wynne <matt at mattwynne.net> wrote: >> >> On 7 Mar 2012, at 11:39, Morten M?ller Riis wrote: >> >> On Mar 7, 2012, at 8:22 AM, Matt Wynne wrote: >> >> >> Hi all, >> >> I''m spec''ing a method that yields a value. Right now, I spec it like this: >> >> result = nil >> thing.do_stuff { |value| result = value } >> result.should == expected >> >> This feels like too much ceremony. What I want to do is something more this: >> >> thing.do_stuff.should yield_value(expected) >> >> Is there anything built into RSpec to let me do this? If not, how do other >> people test yields? >> >> cheers, >> Matt >> >> >> How about this? >> >> thing.do_stuff(&:to_s).should == expected >> >> >> Yes, that''s a neat hack, but I''d prefer to be able to assert on the actual >> yielded value, instead of the result of calling an arbitrary method on it. >> >> Doesn''t anyone else do this? >> >> cheers, >> Matt >> >> -- >> Freelance programmer & coach >> Author, http://pragprog.com/book/hwcuc/the-cucumber-book >> Founder, http://www.relishapp.com/ >> Twitter, https://twitter.com/mattwynne >> >> >> >> _______________________________________________ >> rspec-users mailing list >> rspec-users at rubyforge.org >> http://rubyforge.org/mailman/listinfo/rspec-users > > > > -- > > -- > @zachdennis > http://www.continuousthinking.com > http://www.mutuallyhuman.com > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-userscheers, Matt -- Freelance programmer & coach Author, http://pragprog.com/book/hwcuc/the-cucumber-book Founder, http://www.relishapp.com/ Twitter, https://twitter.com/mattwynne -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20120307/22d0cbc2/attachment.html>
On 7 Mar 2012, at 18:16, David Chelimsky wrote:> On Wed, Mar 7, 2012 at 11:56 AM, Matt Wynne <matt at mattwynne.net> wrote: >> >> On 7 Mar 2012, at 11:39, Morten M?ller Riis wrote: >> >> On Mar 7, 2012, at 8:22 AM, Matt Wynne wrote: >> >> >> Hi all, >> >> I''m spec''ing a method that yields a value. Right now, I spec it like this: >> >> result = nil >> thing.do_stuff { |value| result = value } >> result.should == expected >> >> This feels like too much ceremony. What I want to do is something more this: >> >> thing.do_stuff.should yield_value(expected) >> >> Is there anything built into RSpec to let me do this? If not, how do other >> people test yields? >> >> cheers, >> Matt >> >> >> How about this? >> >> thing.do_stuff(&:to_s).should == expected >> >> >> Yes, that''s a neat hack, but I''d prefer to be able to assert on the actual >> yielded value, instead of the result of calling an arbitrary method on it. > > thing.do_stuff(&:self) would be a bit less arbitrary :)It would, but does it work? I assumed it would too but here on my Ruby 1.9.2 it gives me a NoMethodError :( cheers, Matt -- Freelance programmer & coach Author, http://pragprog.com/book/hwcuc/the-cucumber-book Founder, http://www.relishapp.com/ Twitter, https://twitter.com/mattwynne -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20120307/6014823e/attachment-0001.html>
On Wed, Mar 7, 2012 at 2:32 PM, Matt Wynne <matt at mattwynne.net> wrote:> > On 7 Mar 2012, at 18:16, David Chelimsky wrote: > > On Wed, Mar 7, 2012 at 11:56 AM, Matt Wynne <matt at mattwynne.net> wrote: > > > On 7 Mar 2012, at 11:39, Morten M?ller Riis wrote: > > > On Mar 7, 2012, at 8:22 AM, Matt Wynne wrote: > > > > Hi all, > > > I''m spec''ing a method that yields a value. Right now, I spec it like this: > > > ? ? result = nil > > ? ? thing.do_stuff { |value| result = value } > > ? ? result.should == expected > > > This feels like too much ceremony. What I want to do is something more this: > > > ? ?thing.do_stuff.should yield_value(expected) > > > Is there anything built into RSpec to let me do this? If not, how do other > > people test yields? > > > cheers, > > Matt > > > > How about this? > > > thing.do_stuff(&:to_s).should == expected > > > > Yes, that''s a neat hack, but I''d prefer to be able to assert on the actual > > yielded value, instead of the result of calling an arbitrary method on it. > > > thing.do_stuff(&:self) would be a bit less arbitrary :) > > > It would, but does it work? > > I assumed it would too but here on my Ruby 1.9.2 it gives me a?NoMethodError :(I had assumed as well, and you know what they say about ASSuming!
&:self won''t work because self isn''t an instance method on the object, eg. some_object.self won''t work either. If you wan''t something cleaner couldn''t you use this method in spec_helper.rb ? def block_yield(object, method) object.send(method) { yield if block_given? } end Then: block_yield(thing, :do_stuff).should == "value" Mvh Morten M?ller Riis On Mar 7, 2012, at 9:42 PM, David Chelimsky wrote:> On Wed, Mar 7, 2012 at 2:32 PM, Matt Wynne <matt at mattwynne.net> wrote: >> >> On 7 Mar 2012, at 18:16, David Chelimsky wrote: >> >> On Wed, Mar 7, 2012 at 11:56 AM, Matt Wynne <matt at mattwynne.net> wrote: >> >> >> On 7 Mar 2012, at 11:39, Morten M?ller Riis wrote: >> >> >> On Mar 7, 2012, at 8:22 AM, Matt Wynne wrote: >> >> >> >> Hi all, >> >> >> I''m spec''ing a method that yields a value. Right now, I spec it like this: >> >> >> result = nil >> >> thing.do_stuff { |value| result = value } >> >> result.should == expected >> >> >> This feels like too much ceremony. What I want to do is something more this: >> >> >> thing.do_stuff.should yield_value(expected) >> >> >> Is there anything built into RSpec to let me do this? If not, how do other >> >> people test yields? >> >> >> cheers, >> >> Matt >> >> >> >> How about this? >> >> >> thing.do_stuff(&:to_s).should == expected >> >> >> >> Yes, that''s a neat hack, but I''d prefer to be able to assert on the actual >> >> yielded value, instead of the result of calling an arbitrary method on it. >> >> >> thing.do_stuff(&:self) would be a bit less arbitrary :) >> >> >> It would, but does it work? >> >> I assumed it would too but here on my Ruby 1.9.2 it gives me a NoMethodError :( > > I had assumed as well, and you know what they say about ASSuming! > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users
I''ve been thinking about this a bit ever since Zach Dennis brought up the issue on another rspec-expectations ticket [1]. I''ve come up with a proof-of-concept matcher that works pretty well, I think [2]. Here''s how you use it: expect { |b| 3.tap(&b) }.to yield_value(3) The argument passed to the expect block is a little weird, given that no other block expectations take a block argument like this. But I don''t see a way around it--for the matcher to detect whether or not an argument is yielded (and what the argument is), it needs to control the block passed to the method-under-test. One big win here over some of the other suggestions I''ve seen is that it works just fine with the current rspec-expectations API (in contrast, some of the other suggestions I''ve seen would special-case this matcher so that `expect` takes multiple arguments for it to work). I also like that it''s built as a block expectation; to me it is in the same category of matchers as the change, raise_error and throw_symbol matchers: it''s something that happens as the result of running a bit of code. If enough people like this we can work on getting it into rspec- expectations as an officially supported matcher. If we did, I''d want to beef it up to be significantly more flexible: # for methods that yield multiple arguments to the block... # yield_value would accept a splat of args, and yield_values would # be a more-grammatically-correct alias. expect { |b| foo.fizz(&b) }.to yield_values(:a, 15) # I''d advocate the matcher using the === operator w/ the given values, # so either of these would work expect { |b| "abc".gsub("a", &b) }.to yield_value(String) expect { |b| "abc".gsub("a", &b) }.to yield_value(/a/) # for cases where you need more control over matching the yielded value, pass a block expect { |b| foo.fizz(&b) }.to yield_value { |val| val.should be_fizzy } Thoughts? [1] https://github.com/rspec/rspec-expectations/pull/119#issuecomment-4520633 [2] https://gist.github.com/2065445
On Mar 17, 2012, at 3:51 PM, Myron Marston wrote:> I''ve been thinking about this a bit ever since Zach Dennis brought up > the issue on another rspec-expectations ticket [1]. I''ve come up with > a proof-of-concept matcher that works pretty well, I think [2]. > Here''s how you use it: > > expect { |b| 3.tap(&b) }.to yield_value(3) > > The argument passed to the expect block is a little weird, given that > no other block expectations take a block argument like this. But I > don''t see a way around it--for the matcher to detect whether or not an > argument is yielded (and what the argument is), it needs to control > the block passed to the method-under-test. One big win here over some > of the other suggestions I''ve seen is that it works just fine with the > current rspec-expectations API (in contrast, some of the other > suggestions I''ve seen would special-case this matcher so that `expect` > takes multiple arguments for it to work). I also like that it''s built > as a block expectation; to me it is in the same category of matchers > as the change, raise_error and throw_symbol matchers: it''s something > that happens as the result of running a bit of code. > > If enough people like this we can work on getting it into rspec- > expectations as an officially supported matcher. If we did, I''d want > to beef it up to be significantly more flexible: > > # for methods that yield multiple arguments to the block... > # yield_value would accept a splat of args, and yield_values would > # be a more-grammatically-correct alias. > expect { |b| foo.fizz(&b) }.to yield_values(:a, 15) > > # I''d advocate the matcher using the === operator w/ the given values, > # so either of these would work > expect { |b| "abc".gsub("a", &b) }.to yield_value(String) > expect { |b| "abc".gsub("a", &b) }.to yield_value(/a/) > > # for cases where you need more control over matching the yielded > value, pass a block > expect { |b| foo.fizz(&b) }.to yield_value { |val| val.should > be_fizzy }Love this.> > Thoughts? > > [1] https://github.com/rspec/rspec-expectations/pull/119#issuecomment-4520633 > [2] https://gist.github.com/2065445 > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users
On Sat, Mar 17, 2012 at 7:52 PM, Justin Ko <jko170 at gmail.com> wrote:> > On Mar 17, 2012, at 3:51 PM, Myron Marston wrote: > >> I''ve been thinking about this a bit ever since Zach Dennis brought up >> the issue on another rspec-expectations ticket [1]. I''ve come up with >> a proof-of-concept matcher that works pretty well, I think [2]. >> Here''s how you use it: >> >> expect { |b| 3.tap(&b) }.to yield_value(3)Thanks for thinking about this some more. I don''t think this will work but I''ve commented on the Gist with a couple examples which help help narrow in the implementation. St. Patty''s night can be rough on the mind so I''m not going to pretend that I can code right now. I''ll follow up tomorrow if someone doesn''t beat me to it! Zach>> >> The argument passed to the expect block is a little weird, given that >> no other block expectations take a block argument like this. ?But I >> don''t see a way around it--for the matcher to detect whether or not an >> argument is yielded (and what the argument is), it needs to control >> the block passed to the method-under-test. ?One big win here over some >> of the other suggestions I''ve seen is that it works just fine with the >> current rspec-expectations API (in contrast, some of the other >> suggestions I''ve seen would special-case this matcher so that `expect` >> takes multiple arguments for it to work). ?I also like that it''s built >> as a block expectation; to me it is in the same category of matchers >> as the change, raise_error and throw_symbol matchers: it''s something >> that happens as the result of running a bit of code. >> >> If enough people like this we can work on getting it into rspec- >> expectations as an officially supported matcher. ?If we did, I''d want >> to beef it up to be significantly more flexible: >> >> # for methods that yield multiple arguments to the block... >> # yield_value would accept a splat of args, and yield_values would >> # be a more-grammatically-correct alias. >> expect { |b| foo.fizz(&b) }.to yield_values(:a, 15) >> >> # I''d advocate the matcher using the === operator w/ the given values, >> # so either of these would work >> expect { |b| "abc".gsub("a", &b) }.to yield_value(String) >> expect { |b| "abc".gsub("a", &b) }.to yield_value(/a/) >> >> # for cases where you need more control over matching the yielded >> value, pass a block >> expect { |b| foo.fizz(&b) }.to yield_value { |val| val.should >> be_fizzy } > > Love this. > >> >> Thoughts? >> >> [1] https://github.com/rspec/rspec-expectations/pull/119#issuecomment-4520633 >> [2] https://gist.github.com/2065445 >> _______________________________________________ >> rspec-users mailing list >> rspec-users at rubyforge.org >> http://rubyforge.org/mailman/listinfo/rspec-users > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users-- -- @zachdennis http://www.continuousthinking.com http://www.mutuallyhuman.com