+3

Tại sao cần sử dụng Factories trong Rails test

Ngày nay, hầu hết các dự án của Rails sử dụng một số form của factories để cài đặt. Vậy những vấn đề nào mà factories có thể giải quyết và tại sao chúng hay đc sử dụng.

Nhiều thông tin

Có một model User với first_name, last_name, location fields. Chúng ta có thể viết 1 test giống như sau:

describe "#full_name" do
  it "combines first and last name" do
    user = User.new(
      first_name: "Joël",
      last_name: "Quenneville",
      location: "Boston"
    )

    expect(user.full_name).to eq "Joël Quenneville"
  end
end

Có quá nhiều thông tin được thể hiện trong test case này. field location không liên quan đến ouput của testcase, và khiến chúng ta khó thể chắc chắn được kết quả của test case nếu ko nhìn vào mã nguồn.

Ít thông tin

it "combines first and last name" do
  expect(the_test_user.full_name).to eq "Joël Quenneville"
end

Nhìn vào đây mình không hiểu được tại sao full_name lại là "Joël Quenneville"? nó đến từ đâu?

Chỉ để có kết quả đúng

it "combines first and last name" do
  user = User.new(first_name: "Joël", last_name: "Quenneville")

  expect(user.full_name).to eq "Joël Quenneville"
end

Nó chỉ đầy đủ số lượng thông tin.Tất cả các dữ liệu ảnh hưởng đến kết quả là có trong thiết lập. Không có dữ liệu không liên quan nào được đưa vào Hai quy tắc chúng ta cần biết khi viết 1 test case đó là:

  1. Bao gồm tất cả dữ liệu ảnh hưởng đến kết quả của test case
  2. Không bao gồm dữ liệu không ảnh hưởng đến kết quả của test case

Những fields ràng buộc

Giả sử chúng ta ràng buộc các trường bắt buộc không để trống:

class User < ApplicationRecord
  validates :first_name, presence: true
  validates :last_name, presence: true
  validates :location, presence: true
end

Nhưng khi viết test thì viết như sau để thỏa mãn quy tắc:

it "downcases the location on save" do
  user = User.new(location: "Boston")

  user.save

  expect(user.location).to eq "boston"
end

Nếu như vậy thì test sẽ bị lỗi ngay, chúng ta sẽ chính sửa 1 chút để tránh exception:

it "downcases the location on save" do
  user = build_user_with_defaults(location: "Boston")

  user.save

  expect(user.location).to eq "boston"
end

def build_user_with_defaults(overrides)
  defaults = {
    first_name: "Default",
    last_name: "Default",
    location: "Default"
  }

  User.new(defaults.merge(overrides))
end

Nhưng chả ai muốn phải viết 1 test case như vậy đúng không ạ? và nó cũng lại thừa các thông tin không cần đến.

Factories

Ý tương lấy từ việc xây dựng các giá trị mặc định trước. Sử dụng FactoryBot chúng ta có thể viết:

factory :user do
  first_name "default"
  last_name "default"
  location "default"
end

sau đó viết test như sau:

it "downcases the location on save" do
  user = create(:user, location: "Boston")

  expect(user.location).to eq "boston"
end

Những vấn đề đã được giải quyết và nhìn code của chúng ta khá gọn gàng.

Tận dụng factories

Giống với cách viết test ban đầu, chúng ta hoàn toàn có thể sử dụng factories để tạo ra các đối tượng với những thông tin khác, có thể không liên quan

it "downcases the location on save" do
  user = create(:user, location: "Boston", first_name: "Joël")

  expect(user.location).to eq "boston"
end

Hoặc nó có thể trả về giá trị mặc định:

it "downcases the location on save" do
  user = create(:user)

  expect(user.location).to eq "default"
end

Kết luận

Trong nhiều trường hợp, bạn không cần sử dụng factory. Nếu object không có thuộc tính bị ràng buộc hoặc bạn không cần tuân theo Rail’s validations cho test của bạn. Test Factories tồn tại để giải quyết một vấn đề cụ thể. Nếu các test case của bạn không bị ảnh hưởng từ vấn đề đó thì không nên sử dụng factory một cách tùy ý. Ngược lại, nếu bạn sử dụng factory, hãy cẩn trọng khi tạo ra các đối tượng khi thay đổi các thuộc tính tùy ý mà không phục vụ cho kết quả của test case. Trong tất cả trường hợp, luôn luôn nhớ ràng tại sao chúng ta sử dụng factories và những vấn đề nó giải quyết sẽ giúp bạn viết test dễ đọc hơn và nhanh hơn.

Tham khảo: https://robots.thoughtbot.com/why-factories


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.