Ruby 3.3 の RSpec 内の Capybara で ArgumentError が発生する問題の解決法
環境
ミドルウェア | バージョン |
---|---|
Ruby | 3.3.5 |
Rails | 6.1.7.9 |
RSpec | 3.13.0 |
Capybara | 3.40.0 |
Rails 以外は現時点(2024 年 10 月 23 日現在)では最新版の環境における情報です。
問題
Ruby 3.0.7 から Ruby 3.3.5 にアップデートしたあと RSpec を実行すると Capybara を使用している部分で ArgumentError が発生するようになりました。
RSpec.describe '/foo', type: :request do
context 'foo' do
let(:html) { Capybara.string response.body }
it "displays the flash message" do
expect(html).to have_css '.success', text: 'Field was created successfully'
end
end
end
Failure/Error: expect(html).to have_css '.success', text: 'Field was created successfully'
ArgumentError:
wrong number of arguments (given 2, expected 1)
解決法
現状では主に 2 種類の解決法があります。
feature specs または system specs を利用する
この問題は request specs を使用している場合に発生するということがわかりました。部分的に system specs に書き換えて実行したところ ArgumentError は発生しないことがわかりました。
RSpec.describe '/foo', type: :system do
context 'foo' do
let(:html) { Capybara.string response.body }
it "displays the flash message" do
expect(html).to have_css '.success', text: 'Field was created successfully'
end
end
end
feature specs, system specs, request specs などの違いについては以下の記事が参考になります。
Capybara のマッチャーを使う(RSpec のマッチャーを使わない)
feature specs や system specs に置き換えるとなると、テストケースが膨大(ファイルが巨大)な場合はすぐに修正するのが難しくこの直し方は現実的ではないかもしれません。あるいは、わけあって request specs を使いたい場合もあるかもしれません。
そのような場合は RSpec のマッチャーの代わりに Capybara のマッチャーを使うことで ArgumentError を回避できます。
RSpec.describe '/foo', type: :request do
context 'foo' do
let(:html) { Capybara.string response.body }
it "displays the flash message" do
expect(html.has_css?('.success', text: 'Field was created successfully')).to be_truthy
end
end
end
変更した部分は以下のとおりです。
- expect(html).to have_css '.success', text: 'Field was created successfully'
+ expect(html.has_css?('.success', text: 'Field was created successfully')).to be_truthy
RSpec のマッチャーに関しては詳しく調べていないのですが、どうやらそちら側に問題があるようなので、それを回避するために Capybara 側のマッチャーを使います。上記の例でいうと have_css
ではなく has_css?
を使い、html
ではなく html.has_css?('.success', text: 'Field was created successfully')
が true
を返すかどうかを判定します。
書き方としてあまりスマートではないですがこれでも ArgumentError を回避できます。将来的には RSpec 側に修正が入りこのような書き方をしなくても済むかもしれません。
なお、今回は have_css
を has_css?
に変える例を挙げましたが、have_link
だったら has_link?
に変える、have_content
だったら has_content?
に変えるなど、適宜変更が必要です。
所感
日本語で調べても英語で調べても Google 検索では大した結果が出てこなくて Capybara のイシュー に情報ないかなと思って探していたらようやく解決策を見つけました。やはり開発元をあたるというのは重要ですね。
あと Capybara の README にも feature specs か system specs を使うように指示があるため README を読むのも大事だなと思いました。
Discussion