Tip nhanh: Không lặp code khi viết Test Validations Model
Bài đăng này đã không được cập nhật trong 7 năm
Tôi đã làm việc trên các ứng dụng và cần viết test cho các model. Tôi đã phải lặp lại các bài test validation cho mỗi trường, mỗi model dẫn đến việc code bị trùng lặp. Vì vậy, tôi sẽ chia sẻ giải pháp cho vấn đề này, sẽ giúp chúng ta tránh lặp lại test cho các validation tương tự nhau trong mỗi model.
Tôi dùng Ruby 2.3.0, Rails 4.2.4. , Minitest và FactoryGirl trong vài viết này. Tôi đã viết một đoạn test cho model Site như sau:
class SiteTest < ActiveSupport::TestCase
def test_should_require_customer_name
site = Site.new
refute site.valid?
refute site.save
assert_operator site.errors.count, :>, 0
assert site.errors.messages.include?(:customer_name)
assert site.errors.messages[:customer_name].include?("can't be blank")
end
def test_should_require_customer_email
site = Site.new
refute site.valid?
refute site.save
assert_operator site.errors.count, :>, 0
assert site.errors.messages.include?(:customer_email)
assert site.errors.messages[:customer_email].include?("can't be blank")
end
def test_should_require_host
site = Site.new
refute site.valid?
refute site.save
assert_operator site.errors.count, :>, 0
assert site.errors.messages.include?(:host)
assert site.errors.messages[:host].include?("can't be blank")
end
def test_should_require_host_to_be_unique
theme = FactoryGirl.create(:theme)
Site.skip_callback(:create, :after, :setup_components)
existing_site = FactoryGirl.create(:site, theme: theme)
Site.after_create(:setup_components)
site = Site.new(host: existing_site.host)
refute site.valid?
refute site.save
assert_operator site.errors.count, :>, 0
assert site.errors.messages.include?(:host)
assert site.errors.messages[:host].include?("has already been taken")
end
def test_should_require_theme
site = Site.new
refute site.valid?
refute site.save
assert_operator site.errors.count, :>, 0
assert site.errors.messages.include?(:theme)
assert site.errors.messages[:theme].include?("can't be blank")
end
def test_should_require_user
site = Site.new
refute site.valid?
refute site.save
assert_operator site.errors.count, :>, 0
assert site.errors.messages.include?(:user)
assert site.errors.messages[:user].include?("can't be blank")
end
end
Kết quả test:
$ ruby -Ilib:test test/models/site_test.rb
SiteTest
test_should_require_user PASS (0.45s)
test_should_require_host PASS (0.01s)
test_should_require_customer_email PASS (0.01s)
test_should_require_host_to_be_unique PASS (0.09s)
test_should_require_theme PASS (0.01s)
test_should_require_customer_name PASS (0.01s)
Finished in 0.58104s
6 tests, 30 assertions, 0 failures, 0 errors, 0 skips
Quá nhiều code giống nhau cho tính năng test đơn giản. Hãy tưởng tượng nếu bạn phải lặp lại nó trong tất cả các model cho tất cả các trường bạn muốn validation.
Tôi không biết liệu có Gem nào DRY điều này hay không, vì tôi không tìm giải pháp cho vấn đề này. Thay vào đó, tôi bắt đầu sử dụng Ruby để khắc phục vấn đề này. Và đây là những gì tôi đã đưa ra:
module TestModelValidations
def self.included(klass)
klass.class_eval do
def self.test_validates_presence_of(*args)
args.each do |field_name|
define_method("test_should_require_#{field_name.to_s}") do
model = self.class.model_klass.new
assert_validation(model, field_name, "can't be blank")
end
end
end
def self.test_validates_uniqueness_of(existing_model, *args)
args.each do |field_name|
define_method("test_should_require_#{field_name.to_s}_to_be_unique") do
params_hash = {}
params_hash[field_name] = existing_model.send(field_name)
model = self.class.model_klass.new(params_hash)
assert_validation(model, field_name, "has already been taken")
end
end
end
private
def assert_validation(model, field_name, error_message)
refute model.valid?
refute model.save
assert_operator model.errors.count, :>, 0
assert model.errors.messages.include?(field_name)
assert model.errors.messages[field_name].include?(error_message)
end
end
end
def model_klass
self.class.name.underscore.split("_test").first.camelize.constantize
end
end
Bạn có thể đặt file này trong test/support/ và require tất cả file trong thư mục support.Trước khi bắt đầu test thêm dòng này vào file test/test_helper.rb:
Dir[Rails.root.join(‘test’, ‘support’, ‘*.rb’)].each { |f| require f }
Bạn chỉ cần include module này trong mỗi file test để sử dụng phiên bản DRYed up của các bài test validation:
class ActiveSupport::TestCase
ActiveRecord::Migration.check_pending!
end
Mở class ActiveSupport :: TestCase và extends nó, đây là class mà mỗi class test model kế thừa. Thêm dòng này vào đó:
include TestModelValidations
Bây giờ class trông như sau:
class ActiveSupport::TestCase
ActiveRecord::Migration.check_pending!
include TestModelValidations
end
Bây giờ chúng tôi đã sẵn sàng để trình bày phiên bản DRIed up:
class SiteTest < ActiveSupport::TestCase
test_validates_presence_of :customer_email, :customer_name, :host, :theme, :user
test_validates_uniqueness_of FactoryGirl.create(:site), :host
end
Vâng, chính là nó . Đó là tất cả những gì cần để test model validations. Hãy tưởng tượng việc này được sử dụng này trong tất cả test model của bạn, hy vọng rằng nó sẽ giúp bạn tiết kiệm hàng trăm dòng code và nỗ lực sao chép/dán. Hãy kiểm tra lại để đảm bảo rằng mọi thứ đang hoạt động như trước đây:
$ ruby -Ilib:test test/models/site_test.rb
SiteTest
test_should_require_customer_name PASS (0.34s)
test_should_require_user PASS (0.01s)
test_should_require_host PASS (0.01s)
test_should_require_host_to_be_unique PASS (0.01s)
test_should_require_theme PASS (0.01s)
test_should_require_customer_email PASS (0.01s)
Finished in 0.39483s
6 tests, 30 assertions, 0 failures, 0 errors, 0 skips
Boom! Tất cả mọi thứ hoạt động như mong đợi, nhưng là code sạch và thuận tiện hơn. Điều này làm cho việc test validation cho model dễ dàng hơn.
test_validates_uniqueness_of FactoryGirl.create(:site), :host
Lệnh validates này xác nhận tính duy nhất của một trường trong model. Đối số đầu tiên là trường hợp test. Sau đối số đầu tiên, là trường của model bạn muón xác định tính duy nhất của trương hợp đó.
Mong rằng sẽ nhận được nhận xét và câu hỏi từ bạn. Tôi thực sự hy vọng điều này sẽ giúp ích cho bạn!
Thank you!
Tài liệu dịch: https://www.sitepoint.com/quick-tip-dry-up-your-model-validations-tests/
All rights reserved