I'd like to test the validation of a model's attribute with rspec and factory_girl. The 'special' thing is, that one attribute (the name) isn't allowed to start with Numbers or special signs like %,&,$, ...
For testing this it would be great to write only one example like
it "is invalid with name starting by special character" do
["1","$","%"].each do |i|
name = i + "test"
FactoryGirl.build(:tutu, name: name).should_not be_valid
end
end
This work's for the first case but it won't return the result for the whole list. Is it possible to tell rspec not to stop on the error?
Do this instead:
["1","$","%"].each do |i|
it "is invalid with name starting by '#{i}'" do
FactoryGirl.build(:tutu, name: "#{i}test").should_not be_valid
end
end
Related
I have the following test in rspec
it 'passes regex rules' do
job = create(:job)
job.valid?
expect(job.title).to match(/\A[\w\d .,:-#]+\z/)
end
This regex pattern matches the model pattern. What is the recommended way to test to make sure this pattern does not change in the model from future developers?
Basically I want to test for conditions that do not fall in the approved: can only have 0-9, A-Z, periods, colons, hypens, underscores, and spaces. No new lines (enter keys)
Update
Based on Generate random string based on Regex? I decided to go with (0..255).map(&:chr).select{|x| x != /\A[\w\d .,:-#]+\z/}.sample(5).join for now which appears to work, thoughts?
Based on the update, I went with the following:
describe 'title' do
let(:bad_string) { (0..255).map(&:chr).select{|x| x != /\A[\w\d .,:-#]+\z/}.sample(20).join }
it 'should exist' do
job = build(:job, title: nil)
job.valid?
expect(job.errors[:title].size).to eq(3)
end
it 'passes regex rules' do
job = build(:job, title: bad_string)
job.valid?
expect(job.errors[:title].size).to eq(1)
end
end
Attempting to write a custom model validation and having some trouble. I'm using a regular expression to confirm that a decimal amount is validated to be in the following format:
First digit between 0 and 4
Format as "#.##" - i.e. a decimal number with precision 3 and scale 2. I want 2 digits behind the decimal.
nil values are okay
while the values are nominally numeric, I decided to give the column a data type of string, in order to make it easier to use a regular expression for comparison, without having to bother with the #to_s method. Since I won't be performing any math with the contents this seemed logical.
The regular expression has been tested on Rubular - I'm very confident with it. I've also defined the method in the ruby console, and it appears to be working fine there. I've followed the general instructions on the Rails Guides for Active Record Validations but I'm still getting validation issues that have me headscratching.
Here is the model validation for the column :bar -
class Foo < ActiveRecord::Base
validate :bar_format
def bar_format
unless :bar =~ /^([0-4]{1}\.{1}\d{2})$/ || :bar == nil
errors.add(:bar, "incorrect format")
end
end
end
The spec for Foo:
require 'rails_helper'
describe Foo, type: :model do
let(:foo) { build(:foo) }
it "has a valid factory" do
expect(foo).to be_valid
end
describe "bar" do
it "can be nil" do
foo = create(:foo, bar: nil)
expect(foo).to be_valid
end
it "accepts a decimal value with precision 3 and scale 2" do
foo = create(:foo, bar: "3.50")
expect(foo).to be_valid
end
it "does not accept a decimal value with precision 4 and scale 3" do
expect(create(:foo, bar: "3.501")).not_to be_valid
end
end
end
All of these specs fail for validation on bar:
ActiveRecord::RecordInvalid:
Validation failed: bar incorrect format
In the ruby console I've copied the method bar_format as follows:
irb(main):074:0> def bar_format(bar)
irb(main):075:1> unless bar =~ /^([0-4]{1}\.{1}\d{2})$/ || bar == nil
irb(main):076:2> puts "incorrect format"
irb(main):077:2> end
irb(main):078:1> end
=> :bar_format
irb(main):079:0> bar_format("3.50")
=> nil
irb(main):080:0> bar_format("0.0")
incorrect format
=> nil
irb(main):081:0> bar_format("3.5")
incorrect format
=> nil
irb(main):082:0> bar_format("3.1234")
incorrect format
=> nil
irb(main):083:0> bar_format("3.00")
=> nil
The method returns nil for a correctly formatted entry, and it returns the error message for an incorrectly formatted entry.
Suspecting this has something to do with the validation logic, but as far as I can understand, validations look at the errors hash to determine if the item is valid or not. The logical structure of my validation matches the structure in the example on the Rails Guides, for custom methods.
* EDIT *
Thanks Lazarus for suggesting that I remove the colon from the :bar so it's not a symbol in the method. After doing that, most of the tests pass. However: I'm getting a weird failure on two tests that I can't understand. The code for the tests:
it "does not accept a decimal value with precision 4 and scale 3" do
expect(create(:foo, bar: "3.501")).not_to be_valid
end
it "generates an error message for an incorrect decimal value" do
foo = create(:foo, bar: "4.506")
expect(scholarship.errors.count).to eq 1
end
After turning the symbol :bar into a variable bar the other tests pass, but for these two I get:
Failure/Error: expect(create(:foo, bar: "3.501")).not_to be_valid
ActiveRecord::RecordInvalid:
Validation failed: 3 501 incorrect format
Failure/Error: foo = create(:bar, min_gpa: "4.506")
ActiveRecord::RecordInvalid:
Validation failed: 4 506 incorrect format
Any ideas why it's turning the input "3.501" to 3 501 and "4.506" to 4 506?
You use the symbol instead of the variable when checking against the regex or for nil.
unless :bar =~ /^([0-4]{1}\.{1}\d{2})$/ || :bar == nil
errors.add(:bar, "incorrect format")
end
Remove the : from the :bar
* EDIT *
It's not the specs that are failing but the model's validations upon creation. You should use build instead of create
Don't use symbol to refer an argument.
class Foo < ActiveRecord::Base
validate :bar_format
def bar_format
unless bar =~ /^([0-4]{1}\.{1}\d{2})$/ || bar == nil
errors.add(:bar, "incorrect format")
end
end
end
But if you want an regex for decimal like '1.0', '1.11', '1111.00' I advise you to use this regex:
/^\d+(\.\d{1,2})?$/
If you can to use regex for money, here is:
/^(\d{1,3}\,){0,}(\d{1,3}\.\d{1,2})$/
Good luck ^^
I wrote this test:
test "email validation should accept valid address" do
valid_addresses = %w[user#eee.com R_RDD#adf.com user#gmail.com hi12#hi.co a]
valid_addresses.each do |e|
#chef.email = e
assert #chef.valid?, '#{e.inspect} should be valid'
end
end
When I do rake test, the message when fail is
1) Failure:
ChefTest#test_email_validation_should_accept_valid_address [/home/ubuntu/workspace/test/models/chef_test.rb:56]:
#{e.inspect} should be valid
20 runs, 23 assertions, 1 failures, 0 errors, 0 skips
Instead of whatever |e| should be...
I want to see something like "a" should be a valid like a more descriptive message to see the variable and inspect method value.
Pleas help.
You need to use string interpolation. Which can be made using "", not ''.
assert #chef.valid?, "'#{e.inspect}' should be valid"
You don't need e.inspect, only e is enough. Like:
assert #chef.valid?, "'#{e}' should be valid"
One more suggestion is, you can use instance of the class ActiveModel::Errors containing all errors :
assert #chef.valid?, #chef.errors[:email]
I'm handling a set of rspec programs and pc seems to be forcing me to convert "should" questions to "expect".
Have been able to handle most, but having problems with the following rspec setup.
Most of the other 'should' formatting involves an answer should == something and is easily converted to expect(passed_in_value).to eql(returned_value).
In this case though, I believe it is passing in a block to add to a given number, however, i and unable to just convert it to
expect(end).to eql(6) or whatever the returned value should be.
Take a look and if you have any thoughts, please pass them on
it "adds one to the value returned by the default block" do
adder do
5
end.should == 6
end
it "adds 3 to the value returned by the default block" do
adder(3) do
5
end.should == 8
end
There're several methods to do that.
result = adder(3) do
5
end
expect(result).to eq(8)
expect do
adder(3) do
5
end
end.to eq(8)
block = -> do
5
end
expect(adder 3, &block).to eq(8)
Example from comments with respond_to:
it "has a #sum method" do
[].should respond_to(:sum) #old syntax
expect([]).to respond_to(:sum) #new syntax
end
Currently i am learning with the youtube video Efficient Rails Test Driven Development - by Wolfram Arnold
One exercise is:
A Person object has an optional middle_name.
I create a migration to add the middle name to the database
rake g migration AddMiddleNameToPerson middle_name:string
and i write a spec
it "can have a middle name"
But i got no idea how to test this issue
how can i test an optional field
thanks for help
Bulleric
To say that an attribute is 'optional' implies that the instance is valid when the attribute is nil. So:
it "does not require a middle name" do
#person = Person.new
#person.valid?
#person.errors[:middle_name].should_not include("can't be blank")
end
If you're using shoulda then this can be made even simpler:
describe Person do
it { should_not validate_presence_of(:middle_name) }
end
Assuming you are using Factor_girl, create two factories,
person1 = Factory.create(:person, :first_name=> "A")
person2 = Factory.create(:person, :first_name=> "A", :middle_name => "M")
Now, in your test, show that person1 and person2 both get saved to the database.
You could do the same with fixtures, if you are not using factory_girl.