Sterling Rose Design Blog

assert_include Workaround

7 Comments
Tags: testing Rails
I’m not sure if there used to be an assert_include method or not (I’ve seen some references to it, but can’t find it anywhere in the Rails API), but I found a workaround.

I have a Color model, and I want the :index action to only show those colors whose deleted value is set to false (it’s more or less what the acts_as_paranoid plugin did/does). My test for the :index action looks like this:

test "should get only colors that are not deleted" do
  first_color = Color.create(:name => 'Blue', :deleted => false)
  second_color = Color.create(:name => 'Red', :deleted => true)
  get :index

  assert_response :success
  assert_not_nil assigns(:colors)
  assert_equal true, assigns(:colors).include?(first_color)
  assert_equal false, assigns(:colors).include?(second_color)
end


There may be other ways to do this (and I certainly welcome comments about that, since I’m pretty new to testing), but it worked for me.
Comments

While things like this are why some people move to rSpec (where assigns(:colors).should include(first_color) would fly), this is workable for test/unit.

assert_equal true, splat can typically be shortened to assert splat. I think there is an assert_false as well, but normally you see it as assert !splat

Two things you might consider:

1) instead of assert_not_nil, maybe assert_equal 2, assigns(:colors).size — that protects you against the possibility that there are other elements in the color list, which would not cause a failure in the current test.

2) Shoulda has an assert_same_elements function, which tests that two lists have the same contents regardless of order. That might also help here.

Jim, Thanks for the comment! I’ve used Rspec before, but it’s been awhile. I’m trying to really get my head around T::U before I consider any alternatives. I appreciate the tip about shortening assert_equal!

Noel, Hmmm, assert_not_nil is (obviously) what came out of the can – hadn’t thought about asserting size. Shoulda is next on my list to learn (after T::U). I’ve also heard something about being able to write your own assertions, but haven’t gotten that far yet. I might end up refactoring some of this test code later when I know a bit more. I appreciate the pointers!

Close, but I would use assert_true and assert_false instead:

assert_true, assigns(:colors).include?(first_color)
assert_false, assigns(:colors).include?(second_color)

Just write the methods yourself if you find yourself using it more often.

def assert_include(collection, *elements)
elements.each do |e|
assert(collection.include?(e), “Expected #{collection.inspect} to include #{e.inspect}, but didn’t”)
end
end

def assert_exclude(collection, *elements)
elements.each do |e|
assert(!collection.include?(e), “Expected #{collection.inspect} not to include #{e} but it did.”)
end
end

I haven’t used test/unit in a very long time now, so I don’t know by heart where to include them. I’m also guessing that most other test frameworks have this assertion (I only know RSpec’s should include for sure).

Ah, and format your comments, at least to preserve newlines ;)

Ryan, I somehow missed that there even was an assert_false. Thanks!

Iain, Sorry. Will put it on the to-do list. ;)


Copyright 2007-2010, Sterling Rose Design. All rights reserved.