Validation and Unit Testing
Validations
• Title should not be empty
• Description should not be empty
• Price should be valid
• Models hook the code up to what’s in the db
• Everything that is put into / read from the db
goes through the model
Verify text fields have content
• app/models/product.rb
• validates :title, :description, :image_url,
:presense => true
• rails c
– p = Product.new
– p.valid? #=> false
– p.errors
Validate price > $0.00
• app/models/product.rb
• validates :price, :numericality =>
{:greater_than_or_equal_to => 0.01}
• p = Product.new({:title => "blah", :description
=> "blah", :image_url => "blah"})
• p.valid?
• p.errors
Validate uniqueness of title
• app/model/product.rb
• validates :title, :uniqueness => true
• p = = Product.new({:title => "blah", :description
=> "blah", :image_url => "blah", :price => "33"})
• p.save
• q = Product.new({:title => "blah", :description =>
"blah", :image_url => "blah", :price => "33"})
• q.valid # => false
• q.errors
Validates :image_url
• validates :image_url, :format => {
:with => %r{.(gif|jpg|png)$}i,
:message => ‘must be a URL for GIF, JPG or PNG
image’
}
• q = Product.new({:title => "blah", :description =>
"blah", :image_url => "blah", :price => "33"})
• q.valid?
• q.errors
What we’ve accomplished
• Product model verifies:
– field’s title, description and image URL are not
empty
– Price is a valid number > $0.01
– Title is unique
– Image URL looks reasonable
• http://localhost:3000/products
rake test
• 7 tests, 9 assertions, 2 failures, 0 errors, 0
skips
• Why are our tests failing?
• We added requirements for “valid” products
Update functional tests
• test/functional/products_controller_test.rb
@update = {
:title => 'Lorem Ipsum',
:description => 'Wibbles are fun',
:image_url => 'lorem.jpg',
:price => 19.95
}
Model Unit Tests
• test/unit/product_test.rb
test "product attributes must not be empty" do
product = Product.new
assert product.invalid?
assert product.errors[:title].any?
assert product.errors[:description].any?
assert product.errors[:price].any?
assert product.errors[:image_url].any?
end
rake test:units
• Runs only unit tests (not the full test suite)
• All unit tests pass!
Test more validations
test "product price must be positive" do
product = Product.new(:title => "My Book", :description => 'yyy', :image_url =>
'zzz.jpg')
product.price = -1
assert product.invalid?
assert_equal "must be greater than or equal to 0.01",
product.errors[:price].join(': ')
product.price = 0
assert product.invalid?
assert_equal "must be greater than or equal to 0.01",
product.errors[:price].join(': ')
product.price = 1
assert product.valid?
end
Test your assumptions
• These tests pass now
• Do your tests fail if you remove the
validation(s)?
Good/Bad Image_url’s
test "image url" do
ok = %w{ fred.gif fred.jpg fred.png FRED.JPG FRED.Jpg
http://a.b.c/x/y/z/fred.gif }
bad = %w{ fred.doc fred.gif/more fred.gif.more }
ok.each do |name|
assert new_product(name).valid?, "#{name} shouldn't be invalid"
end
bad.each do |name|
assert new_product(name).invalid?, "#{name} shouldn't be valid"
end
end
Test Fixtures
• Fills our test database with known sample
data
• Usually stored in CSV or YAML format (YAML is
more common)
• Fixture name must match the table you’re
testing
• YAML requires spaces not tabs, tabs produce a
syntax error
Products Fixture
• test/fixtures/products.yml
ruby:
title: Programming Ruby 1.9
description:
Book on programming Ruby. Commonly called
the "pick-axe" book.
price: 49.50
image_url: ruby.png
Using Fixture Data
• test/unit/product_test.rb
test "product is not valid without a unique title" do
product = Product.new(:title => products(:ruby).title,
:description => "yyy",
:price => 1,
:image_url => "fred.gif")
assert !product.save
assert_equal "has already been taken",
product.errors[:title].join('; ')
end
Commit your work
• git status
• git commit –a –m ‘Validation!’
Homework
• Add a validation that verifies the title is at least
10 characters long
– Checkout the :length argument to validate
• Add a validation that verifies the description is no
more than 50 characters long
• Change the error message on one or more of
your validations
• Pretend we operate a dollar store. Write a
validation that makes sure the price is between
$0.01 and $1.00.
Upgrade to Rails 3.0.3
• vi Gemfile
• bundle install
• rake test

Validation unit testing

  • 1.
  • 2.
    Validations • Title shouldnot be empty • Description should not be empty • Price should be valid • Models hook the code up to what’s in the db • Everything that is put into / read from the db goes through the model
  • 3.
    Verify text fieldshave content • app/models/product.rb • validates :title, :description, :image_url, :presense => true • rails c – p = Product.new – p.valid? #=> false – p.errors
  • 4.
    Validate price >$0.00 • app/models/product.rb • validates :price, :numericality => {:greater_than_or_equal_to => 0.01} • p = Product.new({:title => "blah", :description => "blah", :image_url => "blah"}) • p.valid? • p.errors
  • 5.
    Validate uniqueness oftitle • app/model/product.rb • validates :title, :uniqueness => true • p = = Product.new({:title => "blah", :description => "blah", :image_url => "blah", :price => "33"}) • p.save • q = Product.new({:title => "blah", :description => "blah", :image_url => "blah", :price => "33"}) • q.valid # => false • q.errors
  • 6.
    Validates :image_url • validates:image_url, :format => { :with => %r{.(gif|jpg|png)$}i, :message => ‘must be a URL for GIF, JPG or PNG image’ } • q = Product.new({:title => "blah", :description => "blah", :image_url => "blah", :price => "33"}) • q.valid? • q.errors
  • 7.
    What we’ve accomplished •Product model verifies: – field’s title, description and image URL are not empty – Price is a valid number > $0.01 – Title is unique – Image URL looks reasonable • http://localhost:3000/products
  • 8.
    rake test • 7tests, 9 assertions, 2 failures, 0 errors, 0 skips • Why are our tests failing? • We added requirements for “valid” products
  • 9.
    Update functional tests •test/functional/products_controller_test.rb @update = { :title => 'Lorem Ipsum', :description => 'Wibbles are fun', :image_url => 'lorem.jpg', :price => 19.95 }
  • 10.
    Model Unit Tests •test/unit/product_test.rb test "product attributes must not be empty" do product = Product.new assert product.invalid? assert product.errors[:title].any? assert product.errors[:description].any? assert product.errors[:price].any? assert product.errors[:image_url].any? end
  • 11.
    rake test:units • Runsonly unit tests (not the full test suite) • All unit tests pass!
  • 12.
    Test more validations test"product price must be positive" do product = Product.new(:title => "My Book", :description => 'yyy', :image_url => 'zzz.jpg') product.price = -1 assert product.invalid? assert_equal "must be greater than or equal to 0.01", product.errors[:price].join(': ') product.price = 0 assert product.invalid? assert_equal "must be greater than or equal to 0.01", product.errors[:price].join(': ') product.price = 1 assert product.valid? end
  • 13.
    Test your assumptions •These tests pass now • Do your tests fail if you remove the validation(s)?
  • 14.
    Good/Bad Image_url’s test "imageurl" do ok = %w{ fred.gif fred.jpg fred.png FRED.JPG FRED.Jpg http://a.b.c/x/y/z/fred.gif } bad = %w{ fred.doc fred.gif/more fred.gif.more } ok.each do |name| assert new_product(name).valid?, "#{name} shouldn't be invalid" end bad.each do |name| assert new_product(name).invalid?, "#{name} shouldn't be valid" end end
  • 15.
    Test Fixtures • Fillsour test database with known sample data • Usually stored in CSV or YAML format (YAML is more common) • Fixture name must match the table you’re testing • YAML requires spaces not tabs, tabs produce a syntax error
  • 16.
    Products Fixture • test/fixtures/products.yml ruby: title:Programming Ruby 1.9 description: Book on programming Ruby. Commonly called the "pick-axe" book. price: 49.50 image_url: ruby.png
  • 17.
    Using Fixture Data •test/unit/product_test.rb test "product is not valid without a unique title" do product = Product.new(:title => products(:ruby).title, :description => "yyy", :price => 1, :image_url => "fred.gif") assert !product.save assert_equal "has already been taken", product.errors[:title].join('; ') end
  • 18.
    Commit your work •git status • git commit –a –m ‘Validation!’
  • 19.
    Homework • Add avalidation that verifies the title is at least 10 characters long – Checkout the :length argument to validate • Add a validation that verifies the description is no more than 50 characters long • Change the error message on one or more of your validations • Pretend we operate a dollar store. Write a validation that makes sure the price is between $0.01 and $1.00.
  • 20.
    Upgrade to Rails3.0.3 • vi Gemfile • bundle install • rake test