12/08/2018, 17:26

Rspec - 4 lỗi thiết kế test phổ biến

Làm việc với RoR, chắc hẳn không ai còn xa lạ gì với việc sử dụng Rspec để viết UnitTest. Nó thật sự giúp các DEV kiểm soát tốt hơn mã code của mình, đặc biệt với những hệ thống bussiness phức tạp thì càng cần phải viết UnitTest thật đầy đủ. Tuy nhiên, phải thừa nhận là không phải DEV nào cũng biết ...

Làm việc với RoR, chắc hẳn không ai còn xa lạ gì với việc sử dụng Rspec để viết UnitTest. Nó thật sự giúp các DEV kiểm soát tốt hơn mã code của mình, đặc biệt với những hệ thống bussiness phức tạp thì càng cần phải viết UnitTest thật đầy đủ. Tuy nhiên, phải thừa nhận là không phải DEV nào cũng biết viết Rspec đúng. Và tôi cho rằng thà không viết test còn hơn là viết những đoạn mã test yếu. Bởi vì, nếu chúng ta không viết test thì chúng ta sẽ phải test lại bằng tay, nhưng với 1 đoạn mã rspec yếu, chúng ta sẽ lầm tưởng rằng mọi thứ vẫn OK.

Làm thế nào để phát hiện được một test yếu ? Dưới đây là một số lỗi thường gặp trong quá trình tạo test.

Chúng ta sẽ viết 1 đoạn mã đơn giản và 1 đoạn test yếu và cùng phân tích nó:

module Users
  class NameService
    def initialize(user)
      @user = user
    end
  
    def name
      if user.name.present?
        user.name
      else
        ::ExternalAPI.new(user).get_name
      end
    end
  
    private
    attr_reader :user
  end
end

Class này sẽ return tên của user nếu nó tồn tại, nếu không sẽ lấy tên thông qua API. Chúng ta cùng xem xét đoạn test yếu sau đây:

require 'spec_helper'

describe Users::NameService do
  describe '#name' do
    it 'returns name' do
      user = User.create!(name: 'Mike Black')
      service = described_class.new(user)
      
      expect(service.name).to eq(user.name)
    end
    
    it 'returns name' do
      user = User.create!(name: nil)
      service = described_class.new(user)
      
      expect(service.name).to eq('Mike Jr Black')
    end
  end
end

Vì sao đoạn test này là bị gọi là yếu. Hãy cùng phân tích:

Rspec không thể hiểu được.

Khi chạy Rspec với flag --format documentation, bạn sẽ nhận ra rằng nếu không nhìn vào Class và đoạn code test thì sẽ không tài nào hiểu được method này đang làm gì. Tất nhiên, chúng ta biết được method này return ra tên, nhưng ngoài ra thì không biết thêm thông tin gì cả. Test có thể coi là một nguồn kiến thức tốt nhất về ứng dụng nên việc viết mô tả rõ ràng, dễ hiểu là điều rất quan trọng. Hãy xem đoạn fix sau:

describe Users::NameService do
  describe '#name' do
    it 'returns user name if the user has a name' do
      user = User.create!(name: 'Mike Black')
      service = described_class.new(user)
      
      expect(service.name).to eq(user.name)
    end
    
    it 'returns user name from API if the user does not have a name' do
      user = User.create!(name: nil)
      service = described_class.new(user)
      
      expect(service.name).to eq('Mike Jr Black')
    end
  end
end

Giờ hãy chạy lại Rspec với flag --format documentation để thấy sự khác biệt             </div>
            
            <div class=

0