Spyros
Spyros

Reputation: 48626

Rspec Rails - Name should be valid - some clarifications

i'm into rspec these days, trying to make my models more precise and accurate. Some things are still a bit weird to me about rspec and so i thought it would be nice if someone could clarify.

Let's say that i have a User model. This one has a :name. The name should be between 4..15 characters(that's a secondary objective, at first it must just exist). So now i'm thinking: What is the best way to test that in a manner that assures that this will happen. To test that a user must have a name, i wrote something like this :

describe User do
    let(:user) { User.new(:name => 'lele') }

    it "is not valid without a name" do
        user.name.should == 'lele'
    end
end

Now, i'm not quite sure that this accomplishes exactly what i want. It seems to me that i'm actually testing Rails with this one. Moreover, if i want to check that a name cannot be more than 15 chars and less than 4, how can this be integrated ?

EDIT:

Maybe this is better ?

describe User do
    let(:user) { User.new(:name => 'lele') }

    it "is not valid without a name" do
        user.name.should_not be_empty
    end

end

Upvotes: 6

Views: 5993

Answers (4)

Michael Greenly
Michael Greenly

Reputation: 311

I would use something similar to this

class User < ActiveRecord::Base
  validates_presence_of :name
  validates_length_of :name, :in => 4..15
end


describe User do
  it "validates presence of name" do
    user = User.new
    user.valid?.should be_false
    user.name = "valid name"
    user.valid?.should be_true
  end

  it "validates length of name in 4..15" do
    user = User.new
    user.name = "123"
    user.valid?.should be_false
    user.name = "1234567890123456"
    user.valid?.should be_false
    user.name = "valid name"
    user.valid?.should be_true
  end
end

Most notable is that I'm using active record validations for both conditions. In my examples I don't rely on the error strings. In examples that test the behavior of validations there's no reason to touch the database so I don't. In each example I test the behavior of the object when it's both valid and invalid.

Upvotes: 0

zetetic
zetetic

Reputation: 47548

I like to test the actual error messages for validations:

require 'spec_helper'

describe User do
  let (:user) { User.new }

  it "is invalid without a name" do
    user.valid?
    user.errors[:name].should include("can't be blank")
  end

  it "is invalid when less than 4 characters" do
    user.name = "Foo"
    user.valid?
    user.errors[:name].should include("is too short (minimum is 4 characters)")
  end

  it "is invalid when greater than 15 characters" do
    user.name = "A very, very, very long name"
    user.valid?
    user.errors[:name].should include("is too long (maximum is 15 characters)")
  end

end

It's also helpful to use a factory that builds an object with valid attributes, which you can invalidate one at a time for testing.

Upvotes: 2

pablorc
pablorc

Reputation: 950

I use this way:

describe User do

  it "should have name" do
    lambda{User.create! :name => nil}.should raise_error
  end

  it "is not valid when the name is longer than 15 characters" do
    lambda{User.create! :name => "im a very looooooooong name"}.should raise_error
  end

  it "is not valid when the name is shorter than 4 characters" do
    lambda{User.create! :name => "Tom"}.should raise_error
  end    
end

Upvotes: 5

Dylan Markow
Dylan Markow

Reputation: 124419

You're probably looking for the be_valid matcher:

describe User do
  let(:user) { User.new(:name => 'lele') }

  it "is valid with a name" do
    user.should be_valid
  end

  it "is not valid without a name" do
    user.name = nil
    user.should_not be_valid
  end
end

Upvotes: 15

Related Questions