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 < ApplicationRecord
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 < ApplicationRecord
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
Now run the tests... and watch them fail :-(
rails test
Run options: --seed 31976
# Running:
..F
Failure:
ProductsControllerTest#test_should_create_product [/home/rubys/git/awdwr/edition4/work-233-50/depot/test/controllers/products_controller_test.rb:19]:
"Product.count" didn't change by 1.
Expected: 3
Actual: 2
bin/rails test test/controllers/products_controller_test.rb:18
...F
Failure:
ProductsControllerTest#test_should_update_product [/home/rubys/git/awdwr/edition4/work-233-50/depot/test/controllers/products_controller_test.rb:38]:
Expected response to be a <3XX: redirect>, but was a <200: OK>
bin/rails test test/controllers/products_controller_test.rb:36
Finished in 0.608478s, 11.5041 runs/s, 13.1476 assertions/s.
7 runs, 8 assertions, 2 failures, 0 errors, 0 skips
Solution is simple, provide valid data.
edit test/controllers/products_controller_test.rb
require 'test_helper'
class ProductsControllerTest < ActionDispatch::IntegrationTest
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 products_url
assert_response :success
end
test "should get new" do
get new_product_url
assert_response :success
end
test "should create product" do
assert_difference('Product.count') do
post products_url, params: { product: @update }
end
assert_redirected_to product_url(Product.last)
end
# ...
test "should update product" do
patch product_url(@product), params: { product: @update }
assert_redirected_to product_url(@product)
end
# ...
end
Onto the next failure...
rails test
Run options: --seed 25123
# Running:
.......
Finished in 0.492874s, 14.2024 runs/s, 18.2602 assertions/s.
7 runs, 9 assertions, 0 failures, 0 errors, 0 skips
Update test data
edit test/fixtures/products.yml
# Read about fixtures at
# http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
one:
title: MyString
description: MyText
image_url: lorem.jpg
price: 9.99
two:
title: MyString
description: MyText
image_url: lorem.jpg
price: 9.99
Tests now pass again :-)
rails test
Run options: --seed 19709
# Running:
.......
Finished in 0.483876s, 14.4665 runs/s, 18.5998 assertions/s.
7 runs, 9 assertions, 0 failures, 0 errors, 0 skips