7.2 Iteration B2: Unit Testing 6.3 Playtime
Augment the model with a few vailidity checks.
Various validations: required, numeric, positive, and unique
edit app/models/product.rb
class Product < ActiveRecord::Base
validates :title, :description, :image_url, :presence => true
validates :price, :numericality => {:greater_than_or_equal_to => 0.01}
validates :title, :uniqueness => true
validates :image_url, :allow_blank => true, :format => {
:with => %r{\.(gif|jpg|png)\Z}i,
:message => 'must be a URL for GIF, JPG or PNG image.'
}
end
Demonstrate failures.
get /products/new
post /products
Demonstrate more failures.
get /products/new
post /products
edit app/models/product.rb
class Product < ActiveRecord::Base
validates :title, :description, :image_url, :presence => true
validates :price, :numericality => {:greater_than_or_equal_to => 0.01}
validates :title, :uniqueness => true
validates :image_url, :format => {
:with => %r{\.(gif|jpg|png)\Z}i,
:message => 'must be a URL for GIF, JPG or PNG image.'
}
end
Now run the tests... and watch them fail :-(
rake test
Loaded suite /home/rubys/.rvm/gems/ruby-1.8.7-p374/gems/rake-10.1.1/lib/rake/rake_test_loader
Started
.
Finished in 0.163057 seconds.
1 tests, 1 assertions, 0 failures, 0 errors
Loaded suite /home/rubys/.rvm/gems/ruby-1.8.7-p374/gems/rake-10.1.1/lib/rake/rake_test_loader
Started
[deprecated] I18n.enforce_available_locales will default to true in the future. If you really want to skip validation of your locale you can set I18n.enforce_available_locales = false to avoid this message.
F.....F
Finished in 0.553359 seconds.
1) Failure:
test_should_create_product(ProductsControllerTest) [test/functional/products_controller_test.rb:20]:
"Product.count" didn't change by 1.
<3> expected but was
<2>.
2) Failure:
test_should_update_product(ProductsControllerTest) [test/functional/products_controller_test.rb:39]:
Expected response to be a <:redirect>, but was <200>
7 tests, 9 assertions, 2 failures, 0 errors
Errors running test:functionals!
Solution is simple, provide valid data.
edit test/functional/products_controller_test.rb
require 'test_helper'
class ProductsControllerTest < ActionController::TestCase
setup do
@product = products(:one)
@update = {
:title => 'Lorem Ipsum',
:description => 'Wibbles are fun!',
:image_url => 'lorem.jpg',
:price => 19.95
}
end
test "should get index" do
get :index
assert_response :success
assert_not_nil assigns(:products)
end
test "should get new" do
get :new
assert_response :success
end
test "should create product" do
assert_difference('Product.count') do
post :create, :product => @update
end
assert_redirected_to product_path(assigns(:product))
end
# ...
test "should update product" do
put :update, :id => @product.to_param, :product => @update
assert_redirected_to product_path(assigns(:product))
end
# ...
end
Tests now pass again :-)
rake test
Loaded suite /home/rubys/.rvm/gems/ruby-1.8.7-p374/gems/rake-10.1.1/lib/rake/rake_test_loader
Started
.
Finished in 0.164459 seconds.
1 tests, 1 assertions, 0 failures, 0 errors
Loaded suite /home/rubys/.rvm/gems/ruby-1.8.7-p374/gems/rake-10.1.1/lib/rake/rake_test_loader
Started
[deprecated] I18n.enforce_available_locales will default to true in the future. If you really want to skip validation of your locale you can set I18n.enforce_available_locales = false to avoid this message.
.......
Finished in 0.263317 seconds.
7 tests, 10 assertions, 0 failures, 0 errors