Tìm hiểu gem shoulda matchers trong viết Rspec
1.Giới thiệu Viết sử dụng Rspec để viết test cho các dự án Rails là hết sức quan trọng. Đối với những dự án lớn thì việc viết test sẽ vô cùng phức tạp và mất thời gian.Shoulda Matchers cung cấp cách viết 1 dòng lệnh Rspec dùng để test các chức năng của Rails. Nó giúp bạn viết test 1 cách ngắn ...
1.Giới thiệu
Viết sử dụng Rspec để viết test cho các dự án Rails là hết sức quan trọng. Đối với những dự án lớn thì việc viết test sẽ vô cùng phức tạp và mất thời gian.Shoulda Matchers cung cấp cách viết 1 dòng lệnh Rspec dùng để test các chức năng của Rails. Nó giúp bạn viết test 1 cách ngắn gọn, rõ ràng và ít gặp lỗi hơn. Sử dụng Shoulda Matchers giúp cho việc viết rspec đơn giản, ngắn gọn và thú vị hơn. Bài viết sẽ cho bạn 1 cái nhìn để so sánh giữ việc viết test dùng Should Matchers với viết Rspec thông thường.
2.Cài đặt
Thêm vào Gemfile
group :test, :development do gem 'rspec-rails' gem 'shoulda-matchers' end
Sau đó chạy bundle
3.Hướng dẫn sử dụng
Shoulda Matchers cùng cấp cho ta rất nhiều phương thức dùng để test ví dụ:
ActiveModel:
- have_secure_password
- validate_absence_of
- validate_acceptance_of
- validate_confirmation_of
- validate_exclusion_of
- validate_inclusion_of
- validate_length_of
- validate_numericality_of
- validate_presence_of
Ví dụ : Below is an RSpec unit test for an ActiveModel. Each named test goes through four distinct phases: setup, exercise, verify, and teardown. The first named test ensures that you can't create a valid Contact record without a first_name attribute; the second test makes sure each Contact record has a unique email address, and the third enforces a minimum password length requirement.
Dưới đây là ví dụ viết RSpec cho một ActiveModel. Ví dụ yêu cầu khi tạo 1 Contact:
- Phải có first_name.
- email không được trùng lặp.
- password phải có ít nhất 10 ký tự
describe Contact do it "is invalid without a firstname" do contact = Contact.create(first_name: nil, email: "ted@example.com", password: "empirestatebuilding") contact.valid? expect(contact.errors[:firstname]).to include("can't be blank") end it "is invalid with a duplicate email address" do Contact.create(first_name: "Ted", email: "ted@example.com", password: "empirestatebuilding") contact = Contact.new(first_name: "Robin", email: "ted@example.com", password: "montrealcanadiens") contact.valid? expect(contact.errors[:emal]).to include("has already been taken") end it "is invalid without a minimum password length" do contact_one = Contact.create(first_name: "Ted", email: "ted@example.com", password: "empire") contact_one.valid? expect(Contact.errors[:password]).to include("password is too short") end end
Như bạn thấy ở trên, với cú pháp bình thường bạn phải mất rất nhiều dòng code để có thể kiểm tra được 3 logic ở trên. Nhưng với Shoulda Matchers bạn chỉ cần phải dùng 3 dòng
describe Contact do it { is_expected.to validate_presence_of(:firstname) } it { is_expected.to validate_uniqueness_of(:email) } it { is_expected.to validate_length_of(:password).is_at_least(10) } end
ActiveRecord :
- accept_nested_attributes_for
- belong_to
- define_enum_for
- have_and_belong_to_many
- have_db_column
- have_db_index tests
- have_many
- have_one
- have_readonly_attribute
- serialize
- validate_uniqueness_of
Một ví dụ về test mối quan hệ has_many : Cú pháp Rspec:
describe Contact do it "can have many phone numbers" do contact = Contact.reflect_on_association(:phones) expect(contact.macro).to eql(:has_many) end end
Cú pháp Rspec + Shoulda Matchers :
describe Contact do it { is_expected.to have_many(:phones).dependent(:destroy) } end
ActionController : Controller thường ít khi được viết test nhưng Shoulda Mathcher cũng cung cấp rất đầy đủ các phương thức để ta có thể viết test 1 cách dễ dàng và ngắn gọn nhất.
- filter_param
- permit tests
- redirect_to
- render_template
- render_with_layout
- rescue_from tests
- respond_with tests
- route
- set_session
- set_flash
- use_after_action
- use_around_action
- use_before_action tests
Khi viết test cho 1 controller ta thường quan tâm tới :
- Trạng thái trả về của phương thức
- Controller có render template mong muốn không?
- Controller có render layout mong muốn không?
- Controller có tạo flash messages hay không?
- Thông tin có thay đổi hay bị xóa bỏ hay không?
- Controller có chuyển đến url mới không? Ví dụ :
describe ContactsController do describe "GET #index" do context "when user is logged in" do with :user before do sign_in user get :index end it { is_expected.to respond_with :ok } it { is_expected.to render_with_layout :application } it { is_expected.to render_template :index } end context "when user is logged out" do before do get :index end it { is_expected.to redirect_to new_session_path } it { is_expected.to set_the_flash(:warning).to("Please log in.") } it { is_expected.to set_session(:return_to).to(contacts_path) } end end end
4.Kết luận
Thông qua các ví dụ trên ta có thể dễ dàng nhận thấy được sự đơn giản, tiện lợi trong việc sử dụng Shoulda mathcher trong việc viết Rspec so với cú pháp thông thường. Bạn có thể tìm hiểu nhiều ví dụ của Shoulda mathchers và thông qua đó thực hành, áp dụng vào project của bạn tại :
https://github.com/thoughtbot/shoulda-matchers Chúc các bạn thành công !!!