Trong bài viết này, mình sẽ giới thiệu về cách sử dụng Rspec để kiểm thử chức năng của ứng dụng web Ruby on Rails. Có thể việc viết test sẽ gặp nhiều khó khăn khi mới bắt đầu, tuy nhiên cũng có khá nhiều resources hỗ trợ việc viết test dễ dàng hơn. Hi vọng bài viết này sẽ có ích với các bạn mới bắt đầu tiếp xúc.

Trong bài viết này chúng ta sẽ tìm hiểu những vấn đề sau

  1. Cài đặt và cấu hình

  2. Cài đặt và tạo dữ liệu test sử dụng FactoryBot

Bắt đầu

Ở đây mình sử dụng project có sẵn của mình cho việc demo, mọi người có thể xem tại: https://github.com/framgia/fels_210/pull/14/files

class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
  has_many :lessons
  has_many :activities
  paginates_per Settings.perpage
  VALID_EMAIL_REGEX = /\A[\w+\-.][email protected][a-z\d\-.]+\.[a-z]+\z/i
  scope :order_date_desc, ->{order created_at: :desc}
  scope :select_fields, ->{select :id, :email}
  validates :email, presence: true, length: {maximum: Settings.user.email.maximum_length},
    format: {with: VALID_EMAIL_REGEX},
    uniqueness: {case_sensitive: false}
  validates :password, presence: true, length: {minimum: Settings.user.password.minimum_length}, allow_nil: true
end

1. Cài đặt RSpec, Capybara, Shoulda-Matchers.

Ở đây mình hướng dẫn cho 3 gem cơ bản là RSpec, Capybara, Shoulda-Matchers

1.1 Cài đặt RSpec

Thêm gem rspec-rails vào group :development và :test trong Gemfile

group :development, :test do
  gem "rspec-rails", "~> 3.6"
end

Chạy bundle install và khởi tạo rspec $ bundle install & rails generate rspec:install

Cấu trúc thư mục của Rspec

├── spec
│   ├── controllers
│   ├── helpers
│   ├── models
│   ├── rails_helper.rb
│   └── spec_helper.rb

Rspec phân chia các thư mục theo chức năng tương ứng

spec/controllers: chứa các file test cho controller.

spec/models: chứa các file test cho model.

1.2 Cài đặt Shoulda Matcher

Thêm vào Gemfile gem shoulda-matchers

group :test do
  gem "shoulda-matchers", "~> 3.1"
end

Chạybundle install

Shoulda matchers giúp cho việc viết test dễ dàng hơn, tiết kiệm được thời gian khi viết các test dài và phức tạp, code ngắn gọn, dễ đọc. Tiếp theo, chúng ta cần cung cấp cho shoulda matcher:

– Test framework mà chúng ta sử dụng (rspec, minitest,…)

– Những matcher mà chúng ta muốn sử dụng (active-record, model, controller)

Để shoulda-matchers làm việc với RSpec thêm config sau vào rails_helper.rb

Shoulda::Matchers.configure do |config|
  config.integrate do |with|
    with.test_framework :rspec

    with.library :active_record
    with.library :active_model
    with.library :action_controller
    with.library :rails
  end
end

và config Rspec:

RSpec.configure do |config|
  config.include(Shoulda::Matchers::ActiveModel, type: :model)
  config.include(Shoulda::Matchers::ActiveRecord, type: :model)

  config.fixture_path = "#{::Rails.root}/spec/fixtures"

  config.use_transactional_fixtures = true

  config.infer_spec_type_from_file_location!

  config.filter_rails_from_backtrace!
end

Cuối cùng chúng ta thêm require "shoulda/matchers" ở đầu file rails_helper.rb

1.3 Cài đặt Capybara

Capybara là một framework tự động, giúp chúng ta kiểm tra các ứng dụng web bằng cách mô phỏng cách mà một người dùng thực sự tương tác với ứng dụng của chúng ta.

Thêm gem capybara vào group development và test trong Gemfile ruby gem "capybara" Chạy bundle install

Mở file spec/spec_helper.rb và thêm require capybara

require "capybara/rspec"

2. Cài đặt FactoryBot

Factory bot cho phép chúng ta tạo ra các object cần thiết cho việc test với các giá trị mặc định.

Thêm gem factory_bot_rails vào Gemfile

group :development, :test do
  gem "factory_bot_rails", require: false
end

$ bundle install

Cách tạo một factory

Tạo thư mục factories trong thư mục spec để chứa các file tương ứng với model. Ví dụ: spec/factories/user.rb

FactoryBot.define do
  factory :user do
    sequence(:email){Faker::Internet.email}
    password "foobar"
    password_confirmation "foobar"

    trait :invalid_email do
      email {Faker::Name.name}
    end

    trait :large_avatar do
      avatar_path File.open(Rails.root.join("spec/uploads/large_picture.jpg"))
    end

    trait :small_avatar do
      avatar_path File.open(Rails.root.join("spec/uploads/small_picture.jpg"))
    end

    trait :admin do
      admin true
    end

    trait :user do
      admin false
    end
  end
end

Bây giờ chúng ta đã có thể chạy test thử

$ bundle exec rspec

Mặc định khi chạy lệnh trên RSpec sẽ thực thi toàn bộ file trong thư mục spec

Ta cũng có thể chạy từng phần riêng biệt

  • Chỉ chạy specs cho model

$ bundle exec rspec spec/models

  • Tương tự, Chỉ chạy spec cho UsersController

$ bundle exec rspec spec/controllers/users_controller_spec.rb

Ở các phần sau mình sẽ hướng dẫn chi tiết cách viết test cho Model, Controller và View

Tài liệu tham khảo: https://relishapp.com/rspec/rspec-rails/docs/generators