Zequez
Zequez

Reputation: 3499

During TDD, should I create tests for custom validations? Or I should test the validity of the entire object?

I'm very new on TDD and unit-testing, and I'm having quite a lot of doubts about the correct approach I should take during the tests of the custom model validations.

Suppose I have a custom validation:

User < ActiveRecord::Base
  validate :weird_validation

  def weird_validation
    # Validate the weird attribute
  end
end

Should I take this approach:

context "validation"
  it "pass the validation with weird stuff" do
    user = User.new weird: "something weird"
    user.should be_valid
  end


  it "should't pass the validation with normal stuff" do
    user = User.new weird: "something"
    user.should_not be_valid
    user.errors[:weird].size.should eq 1
  end
end

Or this one:

context "#weird_validation" do
  it "should not add an error if weird is weird" do
    user = User.new
    user.stub(:weird){"something weird"}
    user.errors.should_not_receive :add
    user.weird_validation.should eq true
  end

  it "should add an error if weird is not weird" do
    user = User.new
    user.stub(:weird){"something"}
    user.errors.should_receive(:add).with(:weird, anything())
    user.weird_validation.should eq false
  end
end

So IMHO

The first approach

Pros

Cons

The second approach

Pros

Cons

I personally think the correct approach should be the first one, but I can't avoid to think that I'm relying too much in other methods rather than the one I want to test, and if the test fails it may be because of any method withing the model. For example, it would not validate if the validation of other attribute failed.

Using the second approach I'm practically writing the code twice, which seems like a waste of time and effort. But I'm unit-testing the isolated method about what it should do. (and I'm personally doing this for every single method, which is very bad and time consuming I think)

Is there any midway when it comes to using stubs and mocks? Because I've taken the second approach and I think I'm abusing it.

Upvotes: 1

Views: 197

Answers (1)

Jef
Jef

Reputation: 5474

IMO the second approach is the best one because you test your model properties and validations one at a time (the "unit" part).

To avoid overhead, you may consider using shoulda. It is really efficient for models unit testing. We're usually using a factory_girl/mocha/shoulda combination for functional testing (factory_girl and mocha are also very helpful to test queries and named scopes). Tests are easy to write, read and maintain :

# class UserTest < ActiveSupport::TestCase
# or
# describe 'User' do

  should have_db_column(:weird).of_type(:string).with_options(:limit=>255)
  should allow_value("something weird").for(:weird)
  should_not allow_value("something").for(:weird)
  should ensure_length_of(:weird).is_at_least(1).is_at_most(255)

# end

Shoulda generates positive/negative matchers therefore avoids a lot of code duplication.

Upvotes: 1

Related Questions