Topic: Unit Testing and assert_match

I'm not sure if this is a problem with the code that the test is testing, or the test itself, but I think it's the test so I'm putting it in this section.

I'm trying to ensure that various fields are saved to the database
without html, by stripping tags in before_save.  However I'm having
trouble setting up the unit test for this and I'm not sure if it's my
code or my test that's wrong.

The model code is:

  def before_save
    self.first_name = strip_tags(self.first_name)
    self.last_name = strip_tags(self.last_name)
    self.organisation = strip_tags(self.organisation)
  end

The relevant part of my unit test is (obviously I'm doing for each item
in the before_save bit, but since it's all the same I'm just showing the
one):

    c = Contact.new
    c.first_name = "this"
    c.last_name = "<html>that</html>"
    c.organisation = "there"
    c.email='emailaddress'
    c.save

    assert_match("that", c.last_name)


Problem is that if I do assert_match("<html>that</html>", c.last_name)
it also matches.

What's my problem?  Is it the code or the test?

Also, could someone help me with an assert_no_match regexp.  I hate
regexps!  I would like to do an assert_no_match with <html>that</html> -
except I don't know how to do a regular expression to check for an exact
match with this.

Thanks to any help I can get!

Last edited by Draconid (2007-01-16 11:24:28)

Re: Unit Testing and assert_match

I'm not positive what's happening but it may be that the save doesn't change the c object in your code.  Try getting the record again after the save then do the assert_match.

The regexp for exact match is "<html>that<\/html>"

Re: Unit Testing and assert_match

Thanks for your response.  This is what I'm suspecting is happening too.  However, when I try to do:

u = Contact.find(c.id)

u isn't actually being set to anything and so is coming out as nil - and thus my assertion then fails.

I've tried explicitly setting c.id before saving c but even doing this isn't working.

Re: Unit Testing and assert_match

Ah.. I've just put assert before c.save and it's not saving - this might not be helping matters!

Now to work out why it isn't saving...

Re: Unit Testing and assert_match

Okay, I am officially a muppet.

I'd copied my code from another test which was testing to see if one of the fields was unique or not (which it wasn't).  So of course it wasn't valid and wasn't saving.

Thanks for your help anyway!

Re: Unit Testing and assert_match

So I take it this is solved?

BTW, you can do this:

  def before_save
    %w[first_name last_name organisation].each do |attr|
      self[attr] = strip_tags(self[attr])
    end
  end

Or even better:

  def before_save
    attributes.each do |attr, value|
      self[attr] = strip_tags(value) if value.kind_of? String
    end
  end

Railscasts - Free Ruby on Rails Screencasts

Re: Unit Testing and assert_match

Yes, it's solved.

And thanks for the code.  I've just spent my bus journey home wondering how to better code this since I'm doing it multiple times!  I'm actually going to be doing this in (at least) three different models - how do I put this somewhere that all three models can access it (a helper perhaps)?  (I'm still very new to RoR so while I know in concept what a helper is I have no idea how I implement/use one).

Thanks again for your help.

Re: Unit Testing and assert_match

A helper is used more for views/controllers, but you can take the concept of the helper: a module, and use that:

module StripAttributes
  def before_save
    attributes.each do |attr, value|
      self[attr] = strip_tags(value) if value.kind_of? String
    end
  end
end

# then include into a model
def Foo
  include StripAttributes
end


A better way would be to define a class method which creates this callback automatically. That's a bit more complex though.

Railscasts - Free Ruby on Rails Screencasts

Re: Unit Testing and assert_match

Yes, in my head I was thinking that a class method would be good, but I think that's a little beyond me right now!

Do modules have to be stored anywhere specifically in the rails directory structure?

Thanks.

Re: Unit Testing and assert_match

Nope, they can be stored anywhere as long as they are loaded. You can just put it in the model directory. Or if you want to keep that clean, place it in the "lib" directory. You may need to "require" it in the environment.rb file if you do that though.

Railscasts - Free Ruby on Rails Screencasts

Re: Unit Testing and assert_match

This is working perfectly, thanks!