Custom RSpec Matchers.
Đôi khi kết quả mong đợi của một test của bạn quá lớn khiến cho test của bạn mất đi ý nghĩ ban đầu hoặc bạn phải lặp đi lặp lại rất nhiều đoạn mã giống nhau. Chúng ta biết điều này là không tốt, vậy làm thế nào để giải quyết nó? Một cách khá hiệu quả trong trường hợp này là sử dụng các custom ...
Đôi khi kết quả mong đợi của một test của bạn quá lớn khiến cho test của bạn mất đi ý nghĩ ban đầu hoặc bạn phải lặp đi lặp lại rất nhiều đoạn mã giống nhau. Chúng ta biết điều này là không tốt, vậy làm thế nào để giải quyết nó? Một cách khá hiệu quả trong trường hợp này là sử dụng các custom matcher. Một custom matcher cho phép bạn tạo ra những assertions tùy theo yêu cầu của project (mà không có trong các assertions mặc định của rspec). Ngoài ra, custom matcher khá dễ để tạo và sử dụng.
Để tùy chỉnh matcher ta sử dụng gem rspec-expectations (nằm trong gem rspec), nếu bạn muốn sử dụng với các công cụ khác như Test::Unit, Minitest, hoặc Cucumber thì bạn có thể cài trực tiếp: https://github.com/rspec/rspec-expectations
I.Tùy chỉnh rspec matcher.
1.Tạo matcher, tùy chỉnh message, description:
-
Tạo custom matcher với message mặc định:
- Code tùy chỉnh: Sử dụng phương thức define của RSpec::Matchers
require 'rspec/expectations' RSpec::Matchers.define :be_a_multiple_of do |expected| match do |actual| actual % expected == 0 end end
Phương thức define extend module RSpec::Matchers::DSL
-
Test example:
RSpec.describe 9 do it { is_expected.to be_a_multiple_of(3) } end RSpec.describe 9 do it { is_expected.to be_a_multiple_of(4) } end
-
Kết quả:
Then the exit status should not be 0 And the output should contain "should be a multiple of 3" And the output should contain "Failure/Error: it { is_expected.to be_a_multiple_of(4) }" And the output should contain "2 examples, 1 failures" And the output should contain "expected 9 to be a multiple of 4"
-
Overriding the failure_message
- Code tùy chỉnh: override failure_message method
require 'rspec/expectations' RSpec::Matchers.define :be_a_multiple_of do |expected| match do |actual| actual % expected == 0 end failure_message do |actual| "expected that #{actual} would be a multiple of #{expected}" end end
- Test example
RSpec.describe 9 do it { is_expected.to be_a_multiple_of(4) } end
- Kết quả:
Then the exit status should not be 0 And the stdout should contain "1 example, 1 failure" And the stdout should contain "expected that 9 would be a multiple of 4"
-
Custom description
- Code tùy chỉnh: override description method
require 'rspec/expectations' RSpec::Matchers.define :be_a_multiple_of do |expected| match do |actual| actual % expected == 0 end description do "be multiple of #{expected}" end end
- Test example
RSpec.describe 9 do it { is_expected.to be_a_multiple_of(3) } end RSpec.describe 9 do it { is_expected.not_to be_a_multiple_of(4) } end
- Kết quả:
Then the exit status should be 0 And the stdout should contain "2 examples, 0 failures" And the stdout should contain "should be multiple of 3" And the stdout should contain "should not be multiple of 4"
2. Tùy chỉnh tham số
- Không có tham số:
- Code:
require 'rspec/expectations' RSpec::Matchers.define :have_7_fingers do match do |thing| thing.fingers.length == 7 end end
- Test example:
class Thing def fingers (1..7).collect {"finger"} end end RSpec.describe Thing do it { is_expected.to have_7_fingers } end
- Result:
Then the exit status should be 0 And the stdout should contain "1 example, 0 failures" And the stdout should contain "should have 7 fingers"
- Có nhiều tham số:
- Code:
require 'rspec/expectations' RSpec::Matchers.define :be_the_sum_of do |a,b,c,d| match do |sum| a + b + c + d == sum end end
- Test example:
RSpec.describe 10 do it { is_expected.to be_the_sum_of(1,2,3,4) } end
- Result:
Then the exit status should be 0 And the stdout should contain "1 example, 0 failures" And the stdout should contain "should be the sum of 1, 2, 3, and 4"
- Một khối tham số:
- Code:
require 'rspec/expectations' RSpec::Matchers.define :be_lazily_equal_to do match do |obj| obj == block_arg.call end description { "be lazily equal to #{block_arg.call}" } end
- Test example:
RSpec.describe 10 do it { is_expected.to be_lazily_equal_to { 10 } } end
- Result:
Then the exit status should be 0 And the stdout should contain "1 example, 0 failures" And the stdout should contain "should be lazily equal to 10"