While RSpec is the mainstream testing framework for Rails, I personally prefer Minitest for its clarity and simplicity.
Here are my notes on testing model validations with Minitest.
We’ll test private brands sold by retail companies like SEIYU or Matsumoto Kiyoshi.
Retailer: SalesCompany model
class SalesCompany < ApplicationRecord
has_many :product_brands, dependent: :destroy
# validates
validates :sales_company_name, presence: true, uniqueness: true
end
Private Brand: ProductBrand model
class ProductBrand < ApplicationRecord
belongs_to :sales_company
# validates
validates :product_brand_name, presence: true, uniqueness: true
end
Minitest comes standard with Rails, so there’s no need to install anything extra.
When you create a model, test models and fixtures are automatically created in the test directory.
Here’s what the validation tests for the SalesCompany and ProductBrand models look like:
# test/models/sales_company_test.rb
require 'test_helper'
class SalesCompanyTest < ActiveSupport::TestCase
setup do
@sales_company = sales_companies(:seiyu)
end
test "SalesCompany is valid" do
assert @sales_company.valid?
end
test "sales_company_name is required" do
@sales_company.sales_company_name = nil
assert @sales_company.invalid?
assert_includes @sales_company.errors[:sales_company_name], "can't be blank"
end
test "sales_company_name must be unique" do
duplicate_sales_company = @sales_company.dup
duplicate_sales_company.sales_company_name = @sales_company.sales_company_name
assert_not duplicate_sales_company.valid?
end
end
# test/models/product_brand_test.rb
require 'test_helper'
class ProductBrandTest < ActiveSupport::TestCase
setup do
sales_company = sales_companies(:seiyu)
@product_brand = product_brands(:minasamano_osumitsuki)
end
test "ProductBrand is valid" do
assert @product_brand.valid?
end
test "product_brand_name is required" do
@product_brand.product_brand_name = nil
assert @product_brand.invalid?
assert_includes @product_brand.errors[:product_brand_name], "can't be blank"
end
test "product_brand_name must be unique" do
duplicate_product_brand = @product_brand.dup
duplicate_product_brand.product_brand_name = @product_brand.product_brand_name
assert_not duplicate_product_brand.valid?
end
end
Minitest’s fixtures
are intuitive and easy to understand.
You can use them like sales_companies(:seiyu)
.
# sales_companies.yml
matsumotokiyoshi:
sales_company_name: matsumotokiyoshi
seiyu:
sales_company_name: seiyu
seven_eleven:
sales_company_name: seven-eleven
# product_brands.yml
matsumotokiyoshi:
sales_company_name: matsumotokiyoshi
seiyu:
sales_company_name: seiyu
seven_eleven:
sales_company_name: seven-eleven