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

On Feb 1, 2011, at 3:40 AM, James OBrien wrote:

}
: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

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

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!

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 :slight_smile: and although I’m new to it I
really enjoy rspec!

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

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 L.” [email protected] 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

El 02/02/2011, a las 02:28, Julian L. 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

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 3:47 PM, Wincent C. wrote:

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

That’s hopefully already fairly obvious. Yes, I agree. Program to an
interface. The idea is pretty much scope: ie, it depends what you’re
testing… it’s the behaviour of the thing you’re testing that is
important…

We have application-level scope (“behaviour testing”), class-level scope
(testing that the class does what it’s supposed to) and method-level
scope dependant on what we’re programming, right?

If I’m programming a method, I want to test that it does certain things
(preferably the things it’s supposed to do, right? This is, after all,
what a spec is…).

Binding a set of components together to build an enclosing component,
each component should have tests… including any enclosing components.
Encapsulation of tests… :slight_smile:

Julian.

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 L.” [email protected] 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.

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 C.” [email protected] wrote:

El 02/02/2011, a las 02:28, Julian L. 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

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs