[rspec-users] array order-agnostic matching?

Julian Leviston julian at leviston.net
Tue Feb 1 20:28:20 EST 2011


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 <james at 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 <james at 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 <dchelimsky at 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 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 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

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20110202/5b3e9da3/attachment.html>


More information about the rspec-users mailing list