👀
RSpecのdefine_negated_matcherが便利だった
RSpecで肯定と否定を混ぜた合成式を使いたい場合は、RSpec::Matchers.define_negated_matcher
が便利という話です。
通常、RSpecで「マッチャ合成式(Compound Matcher Expressions)」を使うとき、肯定形と否定形は同時には使えません。マッチャ合成式とは、and
やor
で複数の期待値を確かめる書き方です。
describe 'サンプルテスト' do
it 'aで始まり、oで終わること' do
user = User.new(name: 'taro')
expect(user.name).to start_with('t').and end_with('o')
end
end
(サンプルのテストなので細かいところは気にせず)
このように、肯定and
肯定はOKです。しかし、not_to
と組み合わせて使うことはできません。
it 'aで始まらず、oで終わること' do
user = User.new(name: 'taro')
+ expect(user.name).not_to start_with('a').and end_with('o')
end
「その書き方はサポートされてないけど、代わりにRSpec::Matchers.define_negated_matcher
使ってみたら?」と提案してくれます。
Failure/Error: expect(user.name).not_to start_with('a').and end_with('o')
NotImplementedError:
`expect(...).not_to matcher.and matcher` is not supported, since it creates a bit of an ambiguity. Instead, define negated versions of whatever matchers you wish to negate with `RSpec::Matchers.define_negated_matcher` and use `expect(...).to matcher.and matcher`.
このような場合、自分で否定形のマッチャを定義できます。spec/rails_helper.rb
に次のように記述します。
spec/rails_helper.rb
RSpec::Matchers.define_negated_matcher :not_start_with, :start_with
start_with
の否定形をnot_start_with
として定義しています。
すると、さきほどのテストを次のように書くことができます。
it 'aで始まらず、oで終わること' do
user = User.new(name: 'taro')
+ expect(user.name).to not_start_with('a').and end_with('o')
end
Finished in 0.01318 seconds (files took 0.7407 seconds to load)
1 example, 0 failures
仕事でdefine_negated_matcher
を目にする機会があり、便利だと思ったため記事にしました。
肯定と否定を混ぜた合成式を使いたい場合は、RSpec::Matchers.define_negated_matcher
が便利です。
Discussion