Bắt đầu học Rspec test trên Model

Mở đầu

Rspec test trong Ruby on Rails sẽ được thực hiện trên ba thành phần sau:

  • Model
  • View
  • Controller

Khi mới tìm hiểu RSpec là gì và viết những dòng RSpec đầu tiên thì cách đơn giản nhất là bắt đầu với "Model".

Những thứ cần chuẩn bị

Project của chúng ta cần phải có Gemfile như sau:

  1. Gemfile
 group :development, :test do
  gem 'rspec-rails'
  gem 'factory_girl_rails'
 end
 group :test do
  gem 'faker'
  gem 'capybara'
  gem 'guard-rspec'
  gem 'launchy'
  gem "shoulda-matchers", github: "thoughtbot/shoulda-matchers"
 end

Sau khi chắc chắn các Gemfile của mình có những 'gem' như trên thì ta chạy dòng lệnh sau:

 bundle install
  1. Model trong Project:

Trong bài viết này giả sử chúng ta có 2 model là User và Booking. Mối quan hệ giữa User và Booking là 1-n ( Tức là một User có thể đặt nhiều lần Booking và mỗi Booking chỉ được tạo bởi một User).

  • Đối với model User:
 /* app/models/user.rb */
 class User < ApplicationRecord
     has_many :bookings
 end
  • Đối với model Booking:
 /* app/models/booking.rb */
 class Booking < ApplicationRecord
     belongs_to :users
     validates :booking_from, presence: true
 end

Bắt đầu viết RSpec cho Model

  1. Tạo nơi lưu trữ RSpec code:

Để bắt đầu viết RSpec cho model thì đầu tiên phải tạo thư mục 'spec' trong Project.

  • Thư mục 'spec' là nơi chứa các dòng lệnh RSpec của chúng ta.

Nếu vẫn chưa có thư mục 'spec' thì bạn gõ các dòng lệnh sau:

 [email protected]$ cd your_application
 [email protected]/your_application$ mkdir spec
  1. Tạo code RSpec cho từng Model:

Như đã mô tả ở trên, chúng ta có 2 Model là User và Booking nên sẽ tạo tương ứng 2 tệp tin là 'user_spec.rb' và 'booking_spec.rb' để tiến hành test lần lượt cho 2 model này.

Khi viết Test cho một Model nào đó, ta chỉ cần Test cho 2 vấn đề sau là đủ:

  • Mối quan hệ với các Model khác.
  • Validate dữ liệu.

Do đó đối với mỗi Model ta cần tạo ra bộ khung cho nó bằng cách sử dụng từ khóa 'context' như sau:

/* app/spec/models/user_spec.rb */
 require "rails_helper"
 RSpec.describe User, type: :model do
     context "associations" do
         # We will type something later
     end
     context "validates" do
         # We will type something later
     end
 end

Tương tự với model User thì model Booking như sau:

 /* app/spec/models/booking_spec.rb */
 require "rails_helper"
 RSpec.describe Booking, type: :model do
     context "associations" do
         # We will type something later
     end
     context "validates" do
         # We will type something later
     end
 end

Rspec cho User

Chúng ta đang viết Rspec test cho Model User, do đó cần phải mở thư mục RSpec của model này: 'app/spec/models/user_spec.rb'

Sau khi đã mở thư mục trên thì ta tiến hành từng bước như sau:

  1. Mối quan hệ với các Model khác:

"Một User có 'NHIỀU' Booking" => "User has_many Bookings"

Do đó:

/* app/spec/models/user_spec.rb */
 require "rails_helper"
 RSpec.describe User, type: :model do
     context "associations" do
         it {is_expected.to has_many :bookings}
     end
     context "validates" do
         # We will type something later
     end
 end

Dòng chúng ta vừa thêm vào là

it {is_expected.to has_many :bookings}

Chúng ta sẽ phân tích từng thành phần nhỏ:

  • it: Mô tả một ví dụ, nội dung của ví dụ sẽ nằm trong cặp dấu ngoặc {} theo sau nó.
  • is_expected.to: cú pháp của 'gem shoulda-matchers' mà chúng ta đã cài ở trên.
  • has_many :bookings : Diễn đạt mối quan hệ ta cần Test.
  1. Validate dữ liệu

Do ở trên User của chúng ta không có validates gì nên phần validates này sẽ được đề cập đến ở model Booking.

Rspec cho Booking

Tương tự, chúng ta đang viết Rspec test cho Model Booking, do đó cần phải mở thư mục RSpec của model này: 'app/spec/models/booking_spec.rb'

Sau khi đã mở thư mục trên thì ta tiến hành từng bước như sau:

  1. Mối quan hệ với các Model khác:

"Một Booking tạo bởi duy nhất một User" => "Một booking phụ thuộc vào một User" => "Booking belongs_to User"

Do đó:

/* app/spec/models/booking_spec.rb */
 require "rails_helper"
 RSpec.describe Booking, type: :model do
     context "associations" do
         it {is_expected.to belong_to :user}
     end
     context "validates" do
         # We will type something later
     end
 end

Dòng chúng ta vừa thêm vào là

it {is_expected.to belong_to :user}

Chúng ta sẽ phân tích từng thành phần nhỏ:

  • it và is_expected.to: Đã giải thích ở trên.
  • belong_to :user : Diễn đạt mối quan hệ ta cần Test.
  1. Validate dữ liệu

Ở phần model ta đã validates dữ liệu của Booking như sau:

validates :booking_from, presence: true

Do đó, ở phần context 'validates' ta có:

/* app/spec/models/booking_spec.rb */
 require "rails_helper"
 RSpec.describe Booking, type: :model do
     context "associations" do
         it {is_expected.to belong_to :user}
     end
     context "validates" do
         it {is_expected.to validate_presence_of :booking_from}
     end
 end

Dòng chúng ta vừa thêm vào là

it {is_expected.to validate_presence_of :booking_from}

Chúng ta sẽ phân tích từng thành phần nhỏ:

  • it và is_expected.to: Đã giải thích ở trên.
  • validate_presence_of :booking_from : Cần trường booking_from phải không được nil.

Tổng kết

Vậy chúng ta đã đi qua sơ lược về Test Model trong RSpec, ở phần sau chúng ta sẽ tiếp tục với RSpec Test trong Controller.

Bài viết này được tham khảo từ tài liệu sau:

https://everydayrails.com/2012/03/19/testing-series-rspec-models-factory-girl.html

https://github.com/thoughtbot/shoulda-matchers