Spec for 'an array should not include an item'

Does anyone know how I can write a spec along the lines of this (but a
working implementation);

it “should not include inactive users” do
do_get
assigns[:results].should_not include(users(:inactive_user))
end

I’m a newbie so I’m not capable of explaining why it doesn’t work, but
hopefully someone can set me straight.

Thanks

Neil C. [email protected] writes:

Thanks

What’s the error you’re getting? Because, assuming that stuff is hooked
up properly, this ought to work fine.

Pat

Pat M. wrote:


rspec-users mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/rspec-users

Also, what is your data? The matcher may not work as expected due to
nuances in your data. For example, STI tends to mess things up in cases
like this.

-Ben

Ben M. wrote:

Pat M. wrote:


rspec-users mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/rspec-users

Also, what is your data? The matcher may not work as expected due to
nuances in your data. For example, STI tends to mess things up in cases
like this.

-Ben

Thanks guys. The problem is that it simply doesn’t fail when I expect it
to. If I remove the call to the :inactive_user fixture (i.e. I’m
checking that the results should not include any of the ‘users’ at all),
it still passes. This is the spec in full;

describe “handling GET /searches/people” do

def do_get
ThinkingSphinx::Search.stub!(:search).and_return(users)
get :people, :search => “bob”
end

it “should be successful” do
do_get
response.should be_success
end

it “should render people template” do
do_get
response.should render_template(‘people’)
end

it “should assign an array of user results” do
do_get
assigns[:results].should_not be_nil
end

it "should not include any inactive users in an assigned array of user
results " do
do_get
assigns[:results].should_not include(users(:inactive_user))
end

it "should not include any banned users in an assigned array of user
results " do
do_get
assigns[:results].should_not include(users(:banned))
end

end

Is my stubbing breaking this? I hope not because Thinking SPhinx isn’t
determining the scope of the search in relation to the ‘active’ state of
the users; the search is built on top of a named scope on the User
model;

GET /searches/people

GET /searches/people.xml

def people
@results = User.active.search params[:search], :page =>
params[:page], :per_page => 15

respond_to do |format|
  format.html
  format.xml  { render :xml => @results }
end

end

Cheers

David C. wrote:

On Wed, Oct 1, 2008 at 2:33 AM, Neil C. [email protected]
wrote:

Also, what is your data? The matcher may not work as expected due to
describe “handling GET /searches/people” do

it "should not include any inactive users in an assigned array of user

@results = User.active.search params[:search], :page =>
params[:page], :per_page => 15

respond_to do |format|
format.html
format.xml { render :xml => @results }
end
end

Looks to me like this is testing the User here in addition to the
controller.

I’d recommend this:

@mock_user = mock_model(User)
User.stub!(:search_active).and_return([@mock_user])

This would suggest a new method on User that wraps User.active.search,
which you can drive out with code examples directly on the model,
where the work is being done.

Then you could have only one example that deals w/ the collection of
users assigned for the view:

it “should expose @results for the view” do
do_get
assigns[:results].should = [@mock_user]
end

Then, in the model examples, you could either stub the Sphinx search
or just not use stubs/mocks at all.

HTH,
David

Thanks David. After a couple of reads through I don’t really grasp that.
Where would this go in relation to the controller description I posted
(?);

@mock_user = mock_model(User)
User.stub!(:search_active).and_return([@mock_user])

Would it work in the do_get? Further to this, am I right in thinking
that I would write a spec along these lines;

it “should not expose @results for the view” do
do_get
assigns[:results].should_not == [@mock_user]
end

Also (I’m assuming that the ‘model examples’ are the User model spec),
the user_spec.rb doesn’t have any specs that relate to search. Are you
suggesting that there should be some in there, or, are all your
suggestions all related to the controller example I posted? Please bear
with me, I’m not much of a developer.

On Wed, Oct 1, 2008 at 2:33 AM, Neil C. [email protected]
wrote:

Also, what is your data? The matcher may not work as expected due to
describe “handling GET /searches/people” do

it "should not include any inactive users in an assigned array of user

@results = User.active.search params[:search], :page =>
params[:page], :per_page => 15

respond_to do |format|
format.html
format.xml { render :xml => @results }
end
end

Looks to me like this is testing the User here in addition to the
controller.

I’d recommend this:

@mock_user = mock_model(User)
User.stub!(:search_active).and_return([@mock_user])

This would suggest a new method on User that wraps User.active.search,
which you can drive out with code examples directly on the model,
where the work is being done.

Then you could have only one example that deals w/ the collection of
users assigned for the view:

it “should expose @results for the view” do
do_get
assigns[:results].should = [@mock_user]
end

Then, in the model examples, you could either stub the Sphinx search
or just not use stubs/mocks at all.

HTH,
David

Pat M. wrote:

Neil C. [email protected] writes:

respond_to do |format|
  format.html
  format.xml  { render :xml => @results }
end

end

Cheers

You’re stubbing User.search, but you don’t actually call it. search
ends up being called on a named_scope collection proxy. So I think that
this is using the real implementation of both active and search.

I never saw you post a failure message, so I’m not actually sure what
problem you’re having. A failure message would be helpful.

Pat

Pat, I don’t see an error message but, I was expecting this to fail
(which it doesn’t, therefore suggesting the spec is broken);

it "should not include any inactive users in an assigned array of user
results " do
do_get
assigns[:results].should_not include(users)
end

I was under the assumption that the above spec checks that we don’t have
any of the users fixtures in the :results. The spec uses this;

def do_get
ThinkingSphinx::Search.stub!(:search).and_return(users)
get :people, :search => “bob”
end

…so shouldn’t the spec fail if we’re returning all the users fixtures
when assigns[:results].should_not include(users)?

Thanks

Neil C. [email protected] writes:

respond_to do |format|
  format.html
  format.xml  { render :xml => @results }
end

end

Cheers

You’re stubbing User.search, but you don’t actually call it. search
ends up being called on a named_scope collection proxy. So I think that
this is using the real implementation of both active and search.

I never saw you post a failure message, so I’m not actually sure what
problem you’re having. A failure message would be helpful.

Pat

Neil C. [email protected] writes:

(which it doesn’t, therefore suggesting the spec is broken);
def do_get
ThinkingSphinx::Search.stub!(:search).and_return(users)
get :people, :search => “bob”
end

…so shouldn’t the spec fail if we’re returning all the users fixtures
when assigns[:results].should_not include(users)?

Thanks

Well, flip the should_not to should and it ought to fail, and give you a
bit more info. Or print the stuff out. I imagine what’s ultimately
happening is something along the lines of

[1,2,3].should_not include([1,2,3])

which is true. [1,2,3] is not an element of the array [1,2,3]. I used
a simplified example here but it applies equally to an array of User
objects.

Anyway, what kind of debugging have you done to see what objects you’re
actually dealing with? I think doing “p assigns[:results]” and “p
users” will help point you in the right direction…

Pat

Neil C. [email protected] writes:

…so shouldn’t the spec fail if we’re returning all the users fixtures
which is true. [1,2,3] is not an element of the array [1,2,3]. I used
description);
results
…so I’m one step closer but I’m now a little confused by the other
specs.

They are different. This is similar to the example I posted before:
[].should include([])

that will fail…
[[]].should include([])

will pass. Do you see the difference? One of them is an empty array,
and one of them is an array containing a single element (which is itself
an empty array).

nil and [] are not equivalent in Ruby.

Anyway, I’m pretty convinced that your stubbing isn’t working at all.
You can verify this by changing
ThinkingSphinx::Search.stub!(:search).and_return(users)
to
ThinkingSphinx::Search.stub!(:search).and_raise(“boom!”)

If your stubbed method is being called then it’ll raise an error, but I
suspect it’s not.

As far as the fixtures stuff, I’m afraid I can’t help much there. I
think rails db fixtures are the devil and so have managed to put them
completely out of my consciousness.

Pat

Pat M. wrote:

Neil C. [email protected] writes:

(which it doesn’t, therefore suggesting the spec is broken);
def do_get
ThinkingSphinx::Search.stub!(:search).and_return(users)
get :people, :search => “bob”
end

…so shouldn’t the spec fail if we’re returning all the users fixtures
when assigns[:results].should_not include(users)?

Thanks

Well, flip the should_not to should and it ought to fail, and give you a
bit more info. Or print the stuff out. I imagine what’s ultimately
happening is something along the lines of

[1,2,3].should_not include([1,2,3])

which is true. [1,2,3] is not an element of the array [1,2,3]. I used
a simplified example here but it applies equally to an array of User
objects.

Anyway, what kind of debugging have you done to see what objects you’re
actually dealing with? I think doing “p assigns[:results]” and “p
users” will help point you in the right direction…

Pat

Thanks Pat. That really helps. If I do the flip (please ignore the spec
description);

it "should not include any inactive users in an assigned array of user
results " do
do_get
assigns[:results].should include(users)
end

Rspec tells me;

should not include any inactive users in an assigned array of user
results
expected [] to include []

I was expecting :results to contain something, otherwise, wouldn’t this
spec fail (?), or is nil different to empty?;

it “should assign an array of user results” do
do_get
assigns[:results].should_not be_nil
end

…so I’m one step closer but I’m now a little confused by the other
specs.

I haven’t done any debugging, I haven’t come across any debugging
techniques within Rspec before - please treat me as an absolute newbie
to this.

Pat M. wrote:

Neil C. [email protected] writes:

…so shouldn’t the spec fail if we’re returning all the users fixtures
which is true. [1,2,3] is not an element of the array [1,2,3]. I used
description);
results
…so I’m one step closer but I’m now a little confused by the other
specs.

They are different. This is similar to the example I posted before:
[].should include([])

that will fail…
[[]].should include([])

will pass. Do you see the difference? One of them is an empty array,
and one of them is an array containing a single element (which is itself
an empty array).

nil and [] are not equivalent in Ruby.

Anyway, I’m pretty convinced that your stubbing isn’t working at all.
You can verify this by changing
ThinkingSphinx::Search.stub!(:search).and_return(users)
to
ThinkingSphinx::Search.stub!(:search).and_raise(“boom!”)

If your stubbed method is being called then it’ll raise an error, but I
suspect it’s not.

As far as the fixtures stuff, I’m afraid I can’t help much there. I
think rails db fixtures are the devil and so have managed to put them
completely out of my consciousness.

Pat

I just tried the raise;

 ThinkingSphinx::Search.stub!(:search).and_raise("BOOM")

and;

RSpec Results
36 examples, 5 failures
Finished in 1.338815 seconds

SearchesController handling GET /searches/people
should be successful
BOOM

should render people template
BOOM

I should have left my mac by now as my brain is pretty much fried by
this of night, but, unless I’m mistaken, that means the stub is working,
right?

I would like to move away from fixtures but it’ll have to wait for now.
I just want to collect the users fixtures through the :people action in
the searches controller and to make sure that a certain user fixture
isn’t among the return users…I didn’t think it would so tricky!
Thanks, though.

Neil C. [email protected] writes:

They are different. This is similar to the example I posted before:

think rails db fixtures are the devil and so have managed to put them

I should have left my mac by now as my brain is pretty much fried by
this of night, but, unless I’m mistaken, that means the stub is working,
right?

Yes, so, that’s progress :slight_smile:

Pat