- vừa được xem lúc

Tìm hiểu cơ bản về Rspec helper methods

0 0 51

Người đăng: Tuan Anh

Theo Viblo Asia

Helper methods

Trong khi sử dụng RSPEC, chắc hẳn các bạn sử dụng rất nhiều letlet!. Nhiều khi bạn sử dụng let hoặc let! rspec đều chạy đúng, có khi lại phải dùng let! mới được mà khi thì nên dùng let để tốt hơn cho hiệu suất.

Bạn đã hiểu rõ về let và let! chưa? Nếu câu trả lời là chưa thì đây là một tài liệu tham khảo cho bạn, còn ngược lại hãy để lại quan điểm của bạn về let và let! nhé. ❤️

let và let! là cái chi chi

Sử dụng let để định nghĩa một memoized helper method (giá trị của method được ghi nhớ). Giá trị trả về của memoized helper method sẽ được cached lại giữa những lần sử dụng nó trong cùng một example nhưng điều này không khả dụng giữa các example khác nhau.

Chú ý: let là lazy-evaluated có nghĩa là nó sẽ không được đánh giá cho đến khi method nó định nghĩa được gọi lần đầu tiên.

Bởi mặc định, let là threadsafe (luồng an toàn), nhưng bạn có thể thiết lập điều này thông qua config.threadsafe, điều này sẽ giúp hiệu suất của let nhanh hơn một chút.

let! giống với let ngoại trừ việc block của let! sẽ được thực thi trong một before hook ẩn. Điều đó đồng nghĩa với việc let! sẽ được thực thi trước mỗi example trong một group example khai báo nó.

Sự khác nhau giữa let và biến instance

Có 2 cách tiếp cập như sau: để định nghĩa ra một biến để sử dụng Với let:

require 'rspec' RSpec.describe User do let(:user) { User.new } it 'does not have an id when first instantiated' do expect(user.id).to be nil end
end

Với before và instance variable:

require 'rspec' RSpec.describe User do before { @user = User.new } it 'does not have an id when first instantiated' do expect(@user.id).to be nil end
end

Điểm khác biệt: Với instance variable trong before hook có thể bị mất từ một file này tới file khác. Với instance variable có thể nil nên dẫn đến nhiều lỗi tiềm ẩn.

Chứng minh let tạo ra một method

Đoạn code dưới đây tạo ra một method my_name và giá trị trả về của nó được cached.

require 'rspec' describe 'my_name' do let(:my_name) do puts 'thinking about what my name is...' 'Jason Swett' end it 'returns my name' do puts my_name() //Cách gọi một method :)) end
end

Kết quả:

$ rspec my_name_spec.rb
thinking about what my name is...
Jason Swett
. Finished in 0.00193 seconds (files took 0.08757 seconds to load)
1 example, 0 failures

Giá trị trả về của method được tạo bằng let sẽ được cached

Đoạn code dưới đây gọi 2 lần method my_name nhưng chỉ in ra “thinking about what my name is…” một lần và kết quả trả về của my_name được in 2 lần. Tại sao?

require 'rspec' describe 'my_name' do let(:my_name) do puts 'thinking about what my name is...' 'Jason Swett' end it 'returns my name' do puts my_name puts my_name end
end

Kết quả:

$ rspec my_name_spec.rb
thinking about what my name is...
Jason Swett
Jason Swett
. Finished in 0.002 seconds (files took 0.08838 seconds to load)
1 example, 0 failures

Đoạn code sau đây cho ta thấy method my_name được thực thi 1 lần và giá trị trả về của method đó sẽ được cached. Cho dù chúng ta gọi method my_name n lần thì kết quả cũng sẽ được lấy từ lần đầu tiên chứ không thực hiện n lần method my_name.

let là lazy evaluation và let! thì không

let Khi nào method do let định nghĩa được gọi thì nó mới thực thi. Code chứng minh:

require 'rspec' describe 'let' do let(:message) do puts 'let block is running' 'VALUE' end it 'does stuff' do puts 'start of example' puts message puts 'end of example' end
end

Kết quả:

$ rspec let_example_spec.rb
start of example
let block is running
VALUE
end of example
. Finished in 0.00233 seconds (files took 0.09836 seconds to load)
1 example, 0 failures

Từ kết quả in ra dễ dàng thấy rằng đến dòng code puts message thì message mới được thực hiện.

let! Đúng theo định nghĩa, let! giống với let ngoại trừ việc block của let! sẽ được thực thi trong một before hook ẩn. Điều đó đồng nghĩa với việc let! sẽ được thực thi trước mỗi example trong một group example khai báo nó.

Code chứng minh:

require 'rspec' describe 'let!' do let!(:message) do puts 'let! block is running' 'VALUE' end it 'does stuff' do puts 'start of example' puts message puts 'end of example' end
end

Kết quả:

$ rspec let_example_spec.rb let! block is running
start of example
VALUE
end of example
. Finished in 0.00224 seconds (files took 0.09131 seconds to load)
1 example, 0 failures

Nhận xét: Kết quả của đoạn code cho thấy “let! block is running” được in ra đầu tiên đồng nghĩa let! được thực thi trước mỗi example trong example group khai báo nó.

Vì let! được chạy trước mỗi example nên bạn cần chú ý đến vị trí khai báo let! để tránh việc nó chạy trước những example không cần thiết. Trong những file rspec siêu bự thì nó sẽ gây ra hiệu suất rất tồi đó.

Theo quan điểm cá nhân thì khi các bạn nên dùng let! để tạo ra một method có xử lý tạo mới một record. Vì khi đó chúng ta có thể biết rõ ràng và chắc chắn record đó được tạo ra trước khi sử dụng record đó trong example nào đó.

Kết luận

Qua bài viết muốn làm rõ khái niệm và cách let và let! hoạt động, cũng như những sự khác biệt giữa chúng. Để chúng ta có thể viết Rspec không chỉ cho nó chạy đúng mà còn có hiệu suất cao nhất.

Bài viết tham khảo:

  1. https://www.codewithjason.com/difference-let-let-instance-variables-rspec/
  2. https://relishapp.com/rspec/rspec-core/v/3-10/docs/helper-methods/let-and-let

Bình luận

Bài viết tương tự

- vừa được xem lúc

Example groups Rspec - Part 1

Quảng cáo phương thuốc quý. Nếu các bạn đã chán ngấy với việc viết và nhìn những dòng code sau đây lặp đi lặp lại thì bài viết này là dành cho bạn.

0 0 16

- vừa được xem lúc

Tìm hiểu Subject Rspec cơ bản

Mở đầu. Khi bắt đầu viết rspec có một keyword mà khiến mình rất khó hiểu và mơ hồ đó là subject. Trong bài viết này sẽ cung cấp cho các bạn đọc những thông tin cơ bản nhất và không còn bối rối với subject nữa. Định nghĩa :.

0 0 29

- vừa được xem lúc

RSpec: sự khác nhau giữa Mocks và Stub

Sau một thời gian tìm hiểu và làm quen với Mocks và Stubs trong RSpec mình vẫn không thể phân biệt rõ ràng Mocks và Stubs nên thường dùng lẫn lộn giữa chúng. Ở chúng có những điểm tương đồng nhưng cũng có sự khác biệt nên sẽ có những trường hợp sử dụng tối ưu riêng.

0 0 91

- vừa được xem lúc

Better rspec

. Developer không chỉ code mà cần phải viết test đi kèm theo với Code. Trong ngôn ngữ Ruby, RSpec là một trong những testing framework được sử dụng phổ biến nhất.

0 0 22

- vừa được xem lúc

Viết Rspec như thế nào cho tốt?

Hồi mình mới sử dụng Rspec mình dường như chưa hiểu thực sự ý nghĩa của viết Unit Test (Rspec) nên chỉ viết cho có, hay chưa có tâm. Viết unit test để làm gì, mặc dù cũng có Google đọc các thể loại ch

0 0 46

- vừa được xem lúc

Ví dụ viết test RSpec và viết code Ruby on Rails

Bài viết này được lấy cảm hứng từ phần thuyết trình của cty S ở Ruby Kaigi 2021. Và để khởi động thì mình sẽ viết về 1 ví dụ unit test.

0 0 37