Viết Rspec.. sau khi code

Xin chào mọi người, hôm nay mình muốn chia sẻ một kinh nghiệm nhỏ của mình khi viết Rspec sau khi code 😃)

Nếu bạn nào chưa biết về Rspec, hãy tìm kiếm theo từ khoá Rspec trên viblo, ít nhất bạn sẽ hình dung được một phần hình hài của rspec. Nếu ngại, thì hãy hiểu đơn giản nó là một thứ dùng để test source code của bạn (để kiểm tra xem source code hiện tại và tương lai có chạy đúng logic không).

Một đoạn code trong model User

def admin?
  admin
end

sẽ có code Rspec như sau:

describe "#admin?" do
  subject {user.admin?}
  context "when admin" do
    it {is_expected.to be true}
  end
  context "when others" do
    it {is_expected.to be false}
  end
end

Mọi tài liệu official đều nói rằng bạn nên viết test trước khi viết code. Nhưng thực tế lại để bạn nghe câu chuyện dò code để viết test cơ 😃)

Bạn sẽ nhìn hàm admin? rồi viết ra đoạn Rspec ở trên để test cho hàm đó passed. Mọi việc vẫn sẽ trôi chảy cho đến một ngày bạn gặp một tảng đá thế này. (À nếu bạn chính là người viết source code thì may ra não bạn tải được, còn nếu bạn chưa biết logic của source thì đây đúng là tảng đá to đùng đấy 😄)

def can_clone?
  depend_on_role
end

private
def depend_on_role
  case role
  when :admin
    do_something_with_admin
  when :manager
    do_something_with_manager
  end
end

def do_something_with_admin
  vn_admin? ? check_vn_condition : check_jp_condition
end
...

Nhìn đống dây mơ rễ má này có chán không cơ chứ. Làm thế nào để test hàm can_clone? bây giờ???

Nghĩ đơn giản thì giả sử user đầu vào có role == :admin thì chỉ cần trả về giá trị của hàm do_something_with_admin thì pass là cái chắc.

Như thế này:

describe "#can_clone?" do
  context "when admin" do
    subject {user.can_clone?}
    it do
      is_expected.to eq user.send(:do_something_with_admin)
    end
  end
end

Dễ hiểu và chắc chắn pass 😃.

Có điều..

Một ngày đẹp zời hàm do_something_with_admin bỗng nhiên được đổi thành thế này:

def do_something_with_admin
  vn_admin? ? check_jp_condition : check_vn_condition
end

Bạn chạy lại Rspec, ồ vẫn passed!!!

Okay.. Dù source code có thay đổi 180 độ thì test vẫn y chang. Vậy là đống Rspec bạn viết chẳng giải quyết được chuyện gì cả. Và nó đúng là 1 eq 1.

Từ nãy đến giờ mình dùng nhân xưng "bạn" để bạn tự đặt mình vào câu chuyện để có thể dễ hiểu hơn. Nhưng thực chất nó là câu chuyện của mình. Và mình muốn chia sẻ để mn không bị lười và lầm lỡ như mình nữa =))

==========

Câu chuyện của mình được giải quyết bằng một số keyword như sau: stub, stub_request, cố gắng, đọc hiểu code, lần mò, QA... Nói chung là kiểu muốn lười thì lại phải chăm đó. 😄

All Rights Reserved