[rspec-users] array order-agnostic matching?
hey, thanks for reading: I have a problem which can be reduced to this, from within an example of mine I call the helper 'expect_call' which is defined thus: def expect_call(*hash*)* *obj.should_receive(:some_ method).with(*hash*)* *end and in one of my examples the 'expected' hash is strictly defined as follows expect_call(*{ :some_key = [1,2,3] }*) however my spec fails because it is actually called with *{ :some_key = [1,3,2] } *or maybe *{ :some_key = [2,3,1] } *or *{ :some_key = [2,1,3] } *i.e. the array part is not in the order i 'expect' BUT i don't actually care about the order. So I would like to be able to change my one example to something like this: expect_call(*{ *:some_key = [1,2,3]*.ignoring_order }*) does such a concept exist or do I have to change the implementation of expect_call to use some sort of custom matcher - I am reluctant to do this since this method is called in other cases where maybe (for arguments sake) I DO care about array ordering within the hash. Hope someone can solve this for me - MUCH appreciation. James ___ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users
Re: [rspec-users] array order-agnostic matching?
On Feb 1, 2011, at 3:40 AM, James OBrien wrote: hey, thanks for reading: I have a problem which can be reduced to this, from within an example of mine I call the helper 'expect_call' which is defined thus: def expect_call(hash) obj.should_receive(:some_ method).with(hash) end and in one of my examples the 'expected' hash is strictly defined as follows expect_call({ :some_key = [1,2,3] }) however my spec fails because it is actually called with { :some_key = [1,3,2] } or maybe { :some_key = [2,3,1] } or { :some_key = [2,1,3] } i.e. the array part is not in the order i 'expect' BUT i don't actually care about the order. So I would like to be able to change my one example to something like this: expect_call({ :some_key = [1,2,3].ignoring_order }) does such a concept exist or do I have to change the implementation of expect_call to use some sort of custom matcher - I am reluctant to do this since this method is called in other cases where maybe (for arguments sake) I DO care about array ordering within the hash. rspec-expectations lets you do this: foo.bar.should =~ [1,2,3] This passes as long as the array contains exactly those three elements in any order. You can use this now in conjunction with rspec-mocks, like this: foo.should_receive(:bar) do |hash| hash[:some_key].should =~ [1,2,3] end It's a bit more verbose than what you're looking for, but it can get you there with rspec as/is today. Going forward, we might want to consider an array_including argument matcher for rspec-mocks. We already have a hash_including matcher that works like this: foo.should_receive(:bar).with(hash_including(:a = 'b')) Similarly we could have: foo.should_receive(:bar).with(array_including(1,2,3)) The only problem with this is the name: array_including could mean different things (ordered/unordered, only these elements or subset, etc). The hash_including matcher is specifically about a subset of a hash. But perhaps we could extend this with something like you proposed above: foo.should_receive(:bar).with(array_including(1,2,3)) foo.should_receive(:bar).with(array_including(1,2,3).ingoring_order) foo.should_receive(:bar).with(array_including(1,2,3).only.ingoring_order) The thing is, I'm not sure this is any better than the example I gave above, which is very precise and works today. Thoughts/opinions welcome. Hope someone can solve this for me - MUCH appreciation. As an aside, when passing a hash as an argument you don't need to use curly braces, as long as the hash is the last argument to the method. These two are equivalent: expect_call(1, :a, {:some_key = 'some value'}) expect_call(1, :a, :some_key = 'some value') HTH, David ___ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users
Re: [rspec-users] array order-agnostic matching?
additionally, since my *foo.should_receive(... *expectation * *is actually in a private helper method ('expect_call') on the example group I will need to pull this code up into a block, since not all callers pass a hash with :some_key set viz: #helper_method *def expect_call foo.should_receiver(:bar) do |hash| yield hash end end* then those examples which dont care about my array ordering problem (or rather care that it is in order!) can just do: *expect_call do |actual_hash| actual_hash.should == {:some = 'expected_value', :other = [4,5,6]} end* and the one case that does care can do: *expect_call do |actual_hash| actual = **actual_hash[:some_key] **actual_hash**[:some_key] = nil **actual_hash.should == { :my = 'expected' :other = 1 :ields = :in_the_hash } actual.should =~ [1,2,3] ** end* does this sound sensible? Thanks so much again - I have your book :) and although I'm new to it I really enjoy rspec! On Tue, Feb 1, 2011 at 8:51 AM, James OBrien ja...@rapleaf.com wrote: ooops, that sent itself early... . . . there are other entries in the hash so presumably I will need something like this foo.should_receive(:bar) do |hash| actual = hash[:some_key] *hash[:some_key] = nil* hash.should == { :my = 'expected' :other = 1 :ields = :in_the_hash } actual.should =~ [1,2,3] end i.e. I assert :some_key and 'the rest' separately. There isn't a way to do this simpler is there? Thanks again David! On Tue, Feb 1, 2011 at 8:46 AM, James OBrien ja...@rapleaf.com wrote: Awesome, thanks David! there are other entries in the hash so presumably I will need something like this i.e. foo.should_receive(:bar) do |hash| actual = hash[:some_key] hash[:some_key].should =~ [1,2,3] hash.shoul end On Tue, Feb 1, 2011 at 4:43 AM, David Chelimsky dchelim...@gmail.comwrote: On Feb 1, 2011, at 3:40 AM, James OBrien wrote: hey, thanks for reading: I have a problem which can be reduced to this, from within an example of mine I call the helper 'expect_call' which is defined thus: def expect_call(*hash*)* *obj.should_receive(:some_ method).with(*hash*)* *end and in one of my examples the 'expected' hash is strictly defined as follows expect_call(*{ :some_key = [1,2,3] }*) however my spec fails because it is actually called with *{ :some_key = [1,3,2] } *or maybe *{ :some_key = [2,3,1] } *or *{ :some_key = [2,1,3] } *i.e. the array part is not in the order i 'expect' BUT i don't actually care about the order. So I would like to be able to change my one example to something like this: expect_call(*{ *:some_key = [1,2,3]*.ignoring_order }*) does such a concept exist or do I have to change the implementation of expect_call to use some sort of custom matcher - I am reluctant to do this since this method is called in other cases where maybe (for arguments sake) I DO care about array ordering within the hash. rspec-expectations lets you do this: foo.bar.should =~ [1,2,3] This passes as long as the array contains exactly those three elements in any order. You can use this now in conjunction with rspec-mocks, like this: foo.should_receive(:bar) do |hash| hash[:some_key].should =~ [1,2,3] end It's a bit more verbose than what you're looking for, but it can get you there with rspec as/is today. Going forward, we might want to consider an array_including argument matcher for rspec-mocks. We already have a hash_including matcher that works like this: foo.should_receive(:bar).with(hash_including(:a = 'b')) Similarly we could have: foo.should_receive(:bar).with(array_including(1,2,3)) The only problem with this is the name: array_including could mean different things (ordered/unordered, only these elements or subset, etc). The hash_including matcher is specifically about a subset of a hash. But perhaps we could extend this with something like you proposed above: foo.should_receive(:bar).with(array_including(1,2,3)) foo.should_receive(:bar).with(array_including(1,2,3).ingoring_order) foo.should_receive(:bar).with(array_including(1,2,3).only.ingoring_order) The thing is, I'm not sure this is any better than the example I gave above, which is very precise and works today. Thoughts/opinions welcome. Hope someone can solve this for me - MUCH appreciation. As an aside, when passing a hash as an argument you don't need to use curly braces, as long as the hash is the last argument to the method. These two are equivalent: expect_call(1, :a, {:some_key = 'some value'}) expect_call(1, :a, :some_key = 'some value') HTH, David ___ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users ___ rspec-users mailing list
Re: [rspec-users] array order-agnostic matching?
ooops, that sent itself early... . . . there are other entries in the hash so presumably I will need something like this foo.should_receive(:bar) do |hash| actual = hash[:some_key] *hash[:some_key] = nil* hash.should == { :my = 'expected' :other = 1 :ields = :in_the_hash } actual.should =~ [1,2,3] end i.e. I assert :some_key and 'the rest' separately. There isn't a way to do this simpler is there? Thanks again David! On Tue, Feb 1, 2011 at 8:46 AM, James OBrien ja...@rapleaf.com wrote: Awesome, thanks David! there are other entries in the hash so presumably I will need something like this i.e. foo.should_receive(:bar) do |hash| actual = hash[:some_key] hash[:some_key].should =~ [1,2,3] hash.shoul end On Tue, Feb 1, 2011 at 4:43 AM, David Chelimsky dchelim...@gmail.comwrote: On Feb 1, 2011, at 3:40 AM, James OBrien wrote: hey, thanks for reading: I have a problem which can be reduced to this, from within an example of mine I call the helper 'expect_call' which is defined thus: def expect_call(*hash*)* *obj.should_receive(:some_ method).with(*hash*)* *end and in one of my examples the 'expected' hash is strictly defined as follows expect_call(*{ :some_key = [1,2,3] }*) however my spec fails because it is actually called with *{ :some_key = [1,3,2] } *or maybe *{ :some_key = [2,3,1] } *or *{ :some_key = [2,1,3] } *i.e. the array part is not in the order i 'expect' BUT i don't actually care about the order. So I would like to be able to change my one example to something like this: expect_call(*{ *:some_key = [1,2,3]*.ignoring_order }*) does such a concept exist or do I have to change the implementation of expect_call to use some sort of custom matcher - I am reluctant to do this since this method is called in other cases where maybe (for arguments sake) I DO care about array ordering within the hash. rspec-expectations lets you do this: foo.bar.should =~ [1,2,3] This passes as long as the array contains exactly those three elements in any order. You can use this now in conjunction with rspec-mocks, like this: foo.should_receive(:bar) do |hash| hash[:some_key].should =~ [1,2,3] end It's a bit more verbose than what you're looking for, but it can get you there with rspec as/is today. Going forward, we might want to consider an array_including argument matcher for rspec-mocks. We already have a hash_including matcher that works like this: foo.should_receive(:bar).with(hash_including(:a = 'b')) Similarly we could have: foo.should_receive(:bar).with(array_including(1,2,3)) The only problem with this is the name: array_including could mean different things (ordered/unordered, only these elements or subset, etc). The hash_including matcher is specifically about a subset of a hash. But perhaps we could extend this with something like you proposed above: foo.should_receive(:bar).with(array_including(1,2,3)) foo.should_receive(:bar).with(array_including(1,2,3).ingoring_order) foo.should_receive(:bar).with(array_including(1,2,3).only.ingoring_order) The thing is, I'm not sure this is any better than the example I gave above, which is very precise and works today. Thoughts/opinions welcome. Hope someone can solve this for me - MUCH appreciation. As an aside, when passing a hash as an argument you don't need to use curly braces, as long as the hash is the last argument to the method. These two are equivalent: expect_call(1, :a, {:some_key = 'some value'}) expect_call(1, :a, :some_key = 'some value') HTH, David ___ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users ___ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users
Re: [rspec-users] array order-agnostic matching?
Awesome, thanks David! there are other entries in the hash so presumably I will need something like this i.e. foo.should_receive(:bar) do |hash| actual = hash[:some_key] hash[:some_key].should =~ [1,2,3] hash.shoul end On Tue, Feb 1, 2011 at 4:43 AM, David Chelimsky dchelim...@gmail.comwrote: On Feb 1, 2011, at 3:40 AM, James OBrien wrote: hey, thanks for reading: I have a problem which can be reduced to this, from within an example of mine I call the helper 'expect_call' which is defined thus: def expect_call(*hash*)* *obj.should_receive(:some_ method).with(*hash*)* *end and in one of my examples the 'expected' hash is strictly defined as follows expect_call(*{ :some_key = [1,2,3] }*) however my spec fails because it is actually called with *{ :some_key = [1,3,2] } *or maybe *{ :some_key = [2,3,1] } *or *{ :some_key = [2,1,3] } *i.e. the array part is not in the order i 'expect' BUT i don't actually care about the order. So I would like to be able to change my one example to something like this: expect_call(*{ *:some_key = [1,2,3]*.ignoring_order }*) does such a concept exist or do I have to change the implementation of expect_call to use some sort of custom matcher - I am reluctant to do this since this method is called in other cases where maybe (for arguments sake) I DO care about array ordering within the hash. rspec-expectations lets you do this: foo.bar.should =~ [1,2,3] This passes as long as the array contains exactly those three elements in any order. You can use this now in conjunction with rspec-mocks, like this: foo.should_receive(:bar) do |hash| hash[:some_key].should =~ [1,2,3] end It's a bit more verbose than what you're looking for, but it can get you there with rspec as/is today. Going forward, we might want to consider an array_including argument matcher for rspec-mocks. We already have a hash_including matcher that works like this: foo.should_receive(:bar).with(hash_including(:a = 'b')) Similarly we could have: foo.should_receive(:bar).with(array_including(1,2,3)) The only problem with this is the name: array_including could mean different things (ordered/unordered, only these elements or subset, etc). The hash_including matcher is specifically about a subset of a hash. But perhaps we could extend this with something like you proposed above: foo.should_receive(:bar).with(array_including(1,2,3)) foo.should_receive(:bar).with(array_including(1,2,3).ingoring_order) foo.should_receive(:bar).with(array_including(1,2,3).only.ingoring_order) The thing is, I'm not sure this is any better than the example I gave above, which is very precise and works today. Thoughts/opinions welcome. Hope someone can solve this for me - MUCH appreciation. As an aside, when passing a hash as an argument you don't need to use curly braces, as long as the hash is the last argument to the method. These two are equivalent: expect_call(1, :a, {:some_key = 'some value'}) expect_call(1, :a, :some_key = 'some value') HTH, David ___ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users ___ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users
Re: [rspec-users] Notes on upgrading from RSpec 1 to RSpec 2
I've started a chart of differences between RSpec 1 and 2 here: http://snyderscribbles.blogspot.com/2011/01/rspec-2-changes-from-rspec-1.html I'll gladly post any new discoveries anyone want to contribute. On Dec 4 2010, 3:22 pm, Jim Morris wolfma...@gmail.com wrote: I am trying to upgrade a Rails 2.2.2app to Rails3, its a pain ;) Part of this is I need to upgrade all my Specs to RSpec2, as this info does not seem to be in any one place, here is a summary of what I needed to do... * needed to rename all my views from .haml to .html.haml, (or .html.erb) although Rails3 seemed ok with the old naming RSpec2 view specs failed to find the templates with the old name. * rewrite all my view specs... - change `...@controller.template.` to `view.` - change `have_tag` to `have_selector` and change the parameters - place holders not supported, need to use #{} - add :content = for any text in second parameter - change `assign[:blah]= :blod` to `assign(:blag, :blod)` - change the describe ... do to have the path to the view rather than text description - change the render '/show' to just render or render :file = 'full template spec' - change have_text to matches(/../) - change response.should to rendered.shoul * modify the controller specs - controller_name is no longer supported, so need to nest all my describes under a top level describe that has the controller name. describe 'UsersController' do or use subject {SomeController.new} (not tested yet) - when using post/delete/put :something, :id = 1 passing in an integer id used to work, now it needs to be a string (probably a rails3 thing) delete :destroy, :id = 1 * helper specs only needed minor changes - change have_tag to have_selector ___rspec-users mailing listrspec-us...@rubyforge.orghttp://rubyforge.org/mailman/listinfo/rspec-users ___ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users
Re: [rspec-users] Notes on upgrading from RSpec 1 to RSpec 2
Most of our RSpec2 conversion has been done since version 2.4, so my report of performance 2-3 times slower than RSpec 1 is based on those releases. On Jan 13, 11:11 am, David Chelimsky dchelim...@gmail.com wrote: On Jan 13, 2011, at 12:36 PM, Kurt wrote: Hi -- Thanks for sharing all your tips. I couldn't understand your line about what replaces have_text, however. I don't see a method called matches or match... I think your list might be the start of an effort by users to document RSpec2the hard way, since a lot has changed that the core team has not documented anywhere. We've found that the Rails3upgradeis some work, but the advantages over Rails 2 are clear. RSpec2, however, is so poorly documented, useful features have been removed for no apparent reason, and any advantages over RSpec1 have not become clear yet (our test suite runs 3 times slower than it did in RSpec1!). re: speed, you be sure toupgradeto rspec-rails-2.2 (I'd go for the latest, 2.4.1), which sped things up considerably. As for docs - official docs are athttp://relishapp.com/rspec. Info about contributing to the docs can be found there and athttp://blog.davidchelimsky.net/2010/12/23/rspec-2-documentation-2/. Thanks in advance for your help. Cheers, David On Dec 4 2010, 3:22 pm, Jim Morris wolfma...@gmail.com wrote: I am trying toupgradea Rails 2.2.2 app to Rails3, its a pain ;) Part of this is I need toupgradeall my Specs toRSpec2, as this info does not seem to be in any one place, here is a summary of what I needed to do... * needed to rename all my views from .haml to .html.haml, (or .html.erb) although Rails3 seemed ok with the old namingRSpec2view specs failed to find the templates with the old name. * rewrite all my view specs... - change `...@controller.template.` to `view.` - change `have_tag` to `have_selector` and change the parameters - place holders not supported, need to use #{} - add :content = for any text in second parameter - change `assign[:blah]= :blod` to `assign(:blag, :blod)` - change the describe ... do to have the path to the view rather than text description - change the render '/show' to just render or render :file = 'full template spec' - changehave_textto matches(/../) - change response.should to rendered.shoul * modify the controller specs - controller_name is no longer supported, so need to nest all my describes under a top level describe that has the controller name. describe 'UsersController' do or use subject {SomeController.new} (not tested yet) - when using post/delete/put :something, :id = 1 passing in an integer id used to work, now it needs to be a string (probably a rails3 thing) delete :destroy, :id = 1 * helper specs only needed minor changes - change have_tag to have_selector ___ rspec-users mailing list rspec-us...@rubyforge.orghttp://rubyforge.org/mailman/listinfo/rspec-users ___ rspec-users mailing list rspec-us...@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users ___ rspec-users mailing list rspec-us...@rubyforge.orghttp://rubyforge.org/mailman/listinfo/rspec-users ___ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users
Re: [rspec-users] Notes on upgrading from RSpec 1 to RSpec 2
On Feb 1, 2011, at 4:23 PM, Kurt wrote: I've started a chart of differences between RSpec 1 and 2 here: http://snyderscribbles.blogspot.com/2011/01/rspec-2-changes-from-rspec-1.html I'll gladly post any new discoveries anyone want to contribute. It would be great if you would contribute these directly to RSpec's docs so everyone can find them and benefit from them. Take a look at: http://relishapp.com/rspec/rspec-core/v/2-4/file/upgrade http://relishapp.com/rspec/rspec-rails/v/2-4/file/upgrade They are just Markdown files, maintained in the rspec projects: https://github.com/rspec/rspec-core/blob/master/features/Upgrade.md https://github.com/rspec/rspec-rails/blob/master/features/Upgrade.md Just submit pull requests and I'll be happy to merge them. Cheers, David On Dec 4 2010, 3:22 pm, Jim Morris wolfma...@gmail.com wrote: I am trying to upgrade a Rails 2.2.2app to Rails3, its a pain ;) Part of this is I need to upgrade all my Specs to RSpec2, as this info does not seem to be in any one place, here is a summary of what I needed to do... * needed to rename all my views from .haml to .html.haml, (or .html.erb) although Rails3 seemed ok with the old naming RSpec2 view specs failed to find the templates with the old name. * rewrite all my view specs... - change `...@controller.template.` to `view.` - change `have_tag` to `have_selector` and change the parameters - place holders not supported, need to use #{} - add :content = for any text in second parameter - change `assign[:blah]= :blod` to `assign(:blag, :blod)` - change the describe ... do to have the path to the view rather than text description - change the render '/show' to just render or render :file = 'full template spec' - change have_text to matches(/../) - change response.should to rendered.shoul * modify the controller specs - controller_name is no longer supported, so need to nest all my describes under a top level describe that has the controller name. describe 'UsersController' do or use subject {SomeController.new} (not tested yet) - when using post/delete/put :something, :id = 1 passing in an integer id used to work, now it needs to be a string (probably a rails3 thing) delete :destroy, :id = 1 * helper specs only needed minor changes - change have_tag to have_selector ___rspec-users mailing listrspec-us...@rubyforge.orghttp://rubyforge.org/mailman/listinfo/rspec-users ___ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users ___ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users
Re: [rspec-users] Notes on upgrading from RSpec 1 to RSpec 2
On Feb 1, 2011, at 4:31 PM, Kurt wrote: Most of our RSpec2 conversion has been done since version 2.4, so my report of performance 2-3 times slower than RSpec 1 is based on those releases. Are you sure that's all RSpec? rspec-core-2.2 actually runs faster than rspec-core-1.x, and a lot of the Rails framework changed as well. And don't forget bundler. There are a lot of moving parts here, so if you can isolate the slow down to RSpec, please let us know what you find so we can address any specific issues. Thanks! David On Jan 13, 11:11 am, David Chelimsky dchelim...@gmail.com wrote: On Jan 13, 2011, at 12:36 PM, Kurt wrote: Hi -- Thanks for sharing all your tips. I couldn't understand your line about what replaces have_text, however. I don't see a method called matches or match... I think your list might be the start of an effort by users to document RSpec2the hard way, since a lot has changed that the core team has not documented anywhere. We've found that the Rails3upgradeis some work, but the advantages over Rails 2 are clear. RSpec2, however, is so poorly documented, useful features have been removed for no apparent reason, and any advantages over RSpec1 have not become clear yet (our test suite runs 3 times slower than it did in RSpec1!). re: speed, you be sure toupgradeto rspec-rails-2.2 (I'd go for the latest, 2.4.1), which sped things up considerably. As for docs - official docs are athttp://relishapp.com/rspec. Info about contributing to the docs can be found there and athttp://blog.davidchelimsky.net/2010/12/23/rspec-2-documentation-2/. Thanks in advance for your help. Cheers, David On Dec 4 2010, 3:22 pm, Jim Morris wolfma...@gmail.com wrote: I am trying toupgradea Rails 2.2.2 app to Rails3, its a pain ;) Part of this is I need toupgradeall my Specs toRSpec2, as this info does not seem to be in any one place, here is a summary of what I needed to do... * needed to rename all my views from .haml to .html.haml, (or .html.erb) although Rails3 seemed ok with the old namingRSpec2view specs failed to find the templates with the old name. * rewrite all my view specs... - change `...@controller.template.` to `view.` - change `have_tag` to `have_selector` and change the parameters - place holders not supported, need to use #{} - add :content = for any text in second parameter - change `assign[:blah]= :blod` to `assign(:blag, :blod)` - change the describe ... do to have the path to the view rather than text description - change the render '/show' to just render or render :file = 'full template spec' - changehave_textto matches(/../) - change response.should to rendered.shoul * modify the controller specs - controller_name is no longer supported, so need to nest all my describes under a top level describe that has the controller name. describe 'UsersController' do or use subject {SomeController.new} (not tested yet) - when using post/delete/put :something, :id = 1 passing in an integer id used to work, now it needs to be a string (probably a rails3 thing) delete :destroy, :id = 1 * helper specs only needed minor changes - change have_tag to have_selector ___ rspec-users mailing list rspec-us...@rubyforge.orghttp://rubyforge.org/mailman/listinfo/rspec-users ___ rspec-users mailing list rspec-us...@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users ___ rspec-users mailing list rspec-us...@rubyforge.orghttp://rubyforge.org/mailman/listinfo/rspec-users ___ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users ___ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users
Re: [rspec-users] array order-agnostic matching?
Does this strike anyone else as odd? Don't you think the test should actually be written IN to the code itself? I guess I'm soft of stipulating a new language here, but perhaps Ruby is flexible enough to enable this. Surely as the private methods of a class change, the testing code HAS to change... therefore isn't it best to actually write the rspec-level tests into the classes themselves as context-sensitive-optionally loaded or not depending on whether you're in testing mode or not Julian On 02/02/2011, at 4:01 AM, James OBrien wrote: additionally, since my foo.should_receive(... expectation is actually in a private helper method ('expect_call') on the example group I will need to pull this code up into a block, since not all callers pass a hash with :some_key set viz: #helper_method def expect_call foo.should_receiver(:bar) do |hash| yield hash end end then those examples which dont care about my array ordering problem (or rather care that it is in order!) can just do: expect_call do |actual_hash| actual_hash.should == {:some = 'expected_value', :other = [4,5,6]} end and the one case that does care can do: expect_call do |actual_hash| actual = actual_hash[:some_key] actual_hash[:some_key] = nil actual_hash.should == { :my = 'expected' :other = 1 :ields = :in_the_hash } actual.should =~ [1,2,3] end does this sound sensible? Thanks so much again - I have your book :) and although I'm new to it I really enjoy rspec! On Tue, Feb 1, 2011 at 8:51 AM, James OBrien ja...@rapleaf.com wrote: ooops, that sent itself early... . . . there are other entries in the hash so presumably I will need something like this foo.should_receive(:bar) do |hash| actual = hash[:some_key] hash[:some_key] = nil hash.should == { :my = 'expected' :other = 1 :ields = :in_the_hash } actual.should =~ [1,2,3] end i.e. I assert :some_key and 'the rest' separately. There isn't a way to do this simpler is there? Thanks again David! On Tue, Feb 1, 2011 at 8:46 AM, James OBrien ja...@rapleaf.com wrote: Awesome, thanks David! there are other entries in the hash so presumably I will need something like this i.e. foo.should_receive(:bar) do |hash| actual = hash[:some_key] hash[:some_key].should =~ [1,2,3] hash.shoul end On Tue, Feb 1, 2011 at 4:43 AM, David Chelimsky dchelim...@gmail.com wrote: On Feb 1, 2011, at 3:40 AM, James OBrien wrote: hey, thanks for reading: I have a problem which can be reduced to this, from within an example of mine I call the helper 'expect_call' which is defined thus: def expect_call(hash) obj.should_receive(:some_ method).with(hash) end and in one of my examples the 'expected' hash is strictly defined as follows expect_call({ :some_key = [1,2,3] }) however my spec fails because it is actually called with { :some_key = [1,3,2] } or maybe { :some_key = [2,3,1] } or { :some_key = [2,1,3] } i.e. the array part is not in the order i 'expect' BUT i don't actually care about the order. So I would like to be able to change my one example to something like this: expect_call({ :some_key = [1,2,3].ignoring_order }) does such a concept exist or do I have to change the implementation of expect_call to use some sort of custom matcher - I am reluctant to do this since this method is called in other cases where maybe (for arguments sake) I DO care about array ordering within the hash. rspec-expectations lets you do this: foo.bar.should =~ [1,2,3] This passes as long as the array contains exactly those three elements in any order. You can use this now in conjunction with rspec-mocks, like this: foo.should_receive(:bar) do |hash| hash[:some_key].should =~ [1,2,3] end It's a bit more verbose than what you're looking for, but it can get you there with rspec as/is today. Going forward, we might want to consider an array_including argument matcher for rspec-mocks. We already have a hash_including matcher that works like this: foo.should_receive(:bar).with(hash_including(:a = 'b')) Similarly we could have: foo.should_receive(:bar).with(array_including(1,2,3)) The only problem with this is the name: array_including could mean different things (ordered/unordered, only these elements or subset, etc). The hash_including matcher is specifically about a subset of a hash. But perhaps we could extend this with something like you proposed above: foo.should_receive(:bar).with(array_including(1,2,3)) foo.should_receive(:bar).with(array_including(1,2,3).ingoring_order) foo.should_receive(:bar).with(array_including(1,2,3).only.ingoring_order) The thing is, I'm not sure this is any better than the example I gave above, which is very precise and
Re: [rspec-users] array order-agnostic matching?
Sorry it was a knee-jerk reaction that was prompted by what you wrote, but not necessarily even connected to it. Essentially, I've been wondering/thinking about this for a very long time (since about 15 years ago when I started writing smalltalk code). I think a general principle of code is that it should be specced from the inside out and simultaneously from the outside in. We have things like cucumber to generally spec from the outside in (ie define an interface according to the user what or whoever that may be), and we have things like rspec to spec from the inside out ...however inside-out specs should be built inline with the code they spec, surely? I mean, just like you *should* have comments and documentation built in, the spec should almost build a bridge from the documentation to the code... It seems rspec is incredibly close to this, much closer than cucumber is to be a very useable outside-in spec system. Essentially I'd stipulate a flow of development that went something like this: 1. Plan 2. Put Plan and Documentation in source code with placeholders 3. Build Spec 4. Build Code An architecture that, when bootstrapped, tests itself to make sure it's not borked before the code runs. (ie it does self-check on startup, essentially). Julian. On 02/02/2011, at 2:36 PM, James OBrien wrote: I don't fully understand this response.. The private method I mentioned was a helper created by me in test code on the example group. Still very interested On Feb 1, 2011 7:28 PM, Julian Leviston jul...@leviston.net wrote: Does this strike anyone else as odd? Don't you think the test should actually be written IN to the code itself? I guess I'm soft of stipulating a new language here, but perhaps Ruby is flexible enough to enable this. Surely as the private methods of a class change, the testing code HAS to change... therefore isn't it best to actually write the rspec-level tests into the classes themselves as context-sensitive-optionally loaded or not depending on whether you're in testing mode or not Julian On 02/02/2011, at 4:01 AM, James OBrien wrote: additionally, since my foo.should_recei... ___ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users ___ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users ___ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users
Re: [rspec-users] array order-agnostic matching?
Sorry but I disagree. Specs should define only the external behavior of an object or service - allowing for confident implementation adjustments against a trusted suite of tests. What you're describing would make refactoring very hard. I think what you say goes against a lot of established theory and best practise. I would like to draw this back to the original question Take care James On Feb 1, 2011 8:16 PM, Julian Leviston jul...@leviston.net wrote: Sorry it was a knee-jerk reaction that was prompted by what you wrote, but not necessarily even connected to it. Essentially, I've been wondering/thinking about this for a very long time (since about 15 years ago when I started writing smalltalk code). I think a general principle of code is that it should be specced from the inside out and simultaneously from the outside in. We have things like cucumber to generally spec from the outside in (ie define an interface according to the user what or whoever that may be), and we have things like rspec to spec from the inside out ...however inside-out specs should be built inline with the code they spec, surely? I mean, just like you *should* have comments and documentation built in, the spec should almost build a bridge from the documentation to the code... It seems rspec is incredibly close to this, much closer than cucumber is to be a very useable outside-in spec system. Essentially I'd stipulate a flow of development that went something like this: 1. Plan 2. Put Plan and Documentation in source code with placeholders 3. Build Spec 4. Build Code An architecture that, when bootstrapped, tests itself to make sure it's not borked before the code runs. (ie it does self-check on startup, essentially). Julian. On 02/02/2011, at 2:36 PM, James OBrien wrote: I don't fully understand this response.. The... ___ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users ___ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users
Re: [rspec-users] array order-agnostic matching?
El 02/02/2011, a las 02:28, Julian Leviston escribió: Surely as the private methods of a class change, the testing code HAS to change... That statement sets off all sorts of alarm bells for me. In order for your specs to be non-brittle, they should be concerned with the externally-visible behavior of the code and not with the internal implementation details. For me, private methods fall under internal implementation details. Being non-brittle and focussed on externally-visible behavior rather than implementation is a valuable attribute for a spec suite to have, because it allows us to refactor and improve the code with confidence that the behavior remains unchanged, but without having to engage in duplicative and error-prone updating of our specs to match the internal changes in implementation. So, if you're feeling the need to spec private methods, its an indication that you could be doing something better, because you're either: - specifying internal implementation details (and if that's the case, why are you specifying it?); or - you've made something private that shouldn't really be that way (and in that case, there are various refactorings you can use to restructure the code in order to make it more amenable to testing) Cheers, Wincent ___ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users
Re: [rspec-users] array order-agnostic matching?
I agree Vincent Can people however please use this trail to help me with my original query. I repeat the private method is declared on the test example group. This is not inside implemenraton code. On Feb 1, 2011 9:21 PM, Wincent Colaiuta w...@wincent.com wrote: El 02/02/2011, a las 02:28, Julian Leviston escribió: Surely as the private methods of a class change, the testing code HAS to change... That statement sets off all sorts of alarm bells for me. In order for your specs to be non-brittle, they should be concerned with the externally-visible behavior of the code and not with the internal implementation details. For me, private methods fall under internal implementation details. Being non-brittle and focussed on externally-visible behavior rather than implementation is a valuable attribute for a spec suite to have, because it allows us to refactor and improve the code with confidence that the behavior remains unchanged, but without having to engage in duplicative and error-prone updating of our specs to match the internal changes in implementation. So, if you're feeling the need to spec private methods, its an indication that you could be doing something better, because you're either: - specifying internal implementation details (and if that's the case, why are you specifying it?); or - you've made something private that shouldn't really be that way (and in that case, there are various refactorings you can use to restructure the code in order to make it more amenable to testing) Cheers, Wincent ___ rspec-users mailing list rspec-users@rubyforge.org ... ___ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users