I have a User model with this validation
validates :name, :lastname, :format => {:with => /^[a-zA-Z]+$/, :message => 'Only letters and spaces allowed.'}
I'm not sure how to properly test it.
I've done a function that returns a random string made by 10 chars from an array of a-zA-z chars.
def get_random_name
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".split('').shuffle[0..10].join
end end
and then I get a new name for each run of my specs.
I don't want to test that it uses some regexp, because then I would be testing the implementation and not the behavior, and I also don't want to test only one hardcoded case.
My questions are: Should I do that? Is it really needed? Is it better or useless? Do you know any better way to test that kind of validations?
EDIT: another question, what about generating invalid random names? is there a way to create random names that includes at least one char outside the allowed values? I can't hardcode an array of all invalid values to randomize it since it would be TOO big
Checkout the open-source project Shoulda Matchers: https://github.com/thoughtbot/shoulda-matchers
Edit: Sorry just noticed that Paul Fioravanti
mentioned Shoulda also. However you don't need to use FactoryGirl to create instances of the model. Using create
isn't necessary for a validation tests.
You can create unit tests directly on the model:
describe User, 'Validations' do
it { should allow_value("Name").for(:name) }
it { should_not allow_value("Inv4lid_").for(:name) }
end
In order to test valid and invalid formats (I think a regex is fine to define a format to validate against), how about defining what you think valid and invalid names are in some helper utility methods that you could perhaps refine over time if necessary. For example:
spec/support/utilities.rb
def valid_names
%w[Homer bart LISA]
end
def invalid_names
%w[BuRn$ 5M1+h3Rs♡]
end
Then, you could write tests for :name
(and :lastname
) using RSpec, shoulda-matchers, and Factory Girl that look something like this:
spec/models/user_spec.rb
describe User do
let(:user) { FactoryGirl.create(:user) }
# ...
describe "validations" do
context "for name, lastname" do
context "when format is invalid" do
invalid_names.each do |invalid_name|
it { should_not allow_value(invalid_name).for(:name) }
it { should_not allow_value(invalid_name).for(:lastname) }
end
end
context "when format is valid" do
valid_names.each do |valid_name|
it { should allow_value(valid_name).for(:name) }
it { should allow_value(valid_name).for(:lastname) }
end
end
# ...
end
# ...
end
# ...
end
If you ever intend to internationalize your app in the future, just remember that not all the world's names conform to this format.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With