patorashのブログ

方向性はまだない

Capybara3にアップデートしたらハマったことをまとめる

長いことCapybara2系を使っていた。ようやくCapybara3系にアップデートする暇が取れたので作業に着手したら、めっちゃテスト落ちた…。ので、その原因と対策を書いていく。

whitespaceが含まれるようになった。

以下のブログ記事にも書かれていますが、半角スペースや改行コードが戻り値に含まれるようになりました。

journal.sooey.com

ですので、passのように、改行コードを含めて記述しなければなりません。

expect(page).to have_content 'foo bar' # => fail
expect(page).to have_content "foo\nbar" # => pass

オマケ

Capybara.default_normalize_ws = trueにすれば、今までと同様の評価になる模様。だけれど、Capybara4では消されるっぽいので、上記の対応をしておいたほうがよさそうです。

page.allがdefault_wait_timeまで待つようになった

これは元々な気もするけれど、Capybara2系のときには起きなかった事で、table要素の中身を掘ってるときに起きました。

contents  = page.all('table tbody tr').map do |row|
              row.all('th,td').map do |cell|
                if cell.all('li').count > 0
                  cell.all('li').map(&:text)
                else
                  cell.text
                end
              end
            end

テーブルのセルの中でliタグがあれば、それは配列として取得、みたいな処理をしているのですが、この処理が全く終わらなくなりました。実際には進んではいたみたいなのですが、どうもif cell.all('li').count > 0のところで、liの存在チェックをCapybara.default_max_wait_timeまで待っているようでした。mapで処理しているので、100セルあればCapybara.default_max_wait_time * 100だけ待たなければなりません…。Capybara2のときは即時評価だったと思うんですが…。なんにしろこれはマズいので、allのところのwaitを変えました。

contents  = page.all('table tbody tr').map do |row|
              row.all('th,td').map do |cell|
                if cell.all('li', wait: 0).count > 0 # => 1秒たりとも待たない!
                  cell.all('li').map(&:text)
                else
                  cell.text
                end
              end
            end

原因不明のエラー

落ちてたテストを直したら再現しなくなったのでちょっとわからないのですが、以下のissueと同じエラーが出ていました。

github.com

どうもCapybara3系とTimecopを使っている場合で起きる、とか。未来に行ったりするとよくないとかは書かれていましたが、該当のテストではそんなこともしてませんでした。落ちたテストの次のテストとの間でエラーが起きるのだろうか…など考えていましたが、もう起きなくなったので、とりあえず放置。また再現したらここに書いていることを思い出すためのメモです、これは。

苦労したこと

何気にシングルクォートで囲んでいるやつをダブルクォートに変換してさらに改行コードを入れて…というのは骨が折れる作業だった。大概は目で確認しながら正規表現で置換していったけれど。とはいえ、ずっと気になっていたバージョンアップができてよかった。