こんにちはこんにちは。
セブンにある蒙古タンメン北極のカップラーメンににんにくのチューブたくさん入れて食べたらお腹がいたくなった辻@dim0627です。
今回はちまちま直してたrspecの話をします。
CIマジで遅い問題
これほんとQOL下がる。そいえば最近は開発時の体験をDXとか言うらしいですね。
この問題は以前僕が居たときからあって、なんでかなーなんでかなーとあんまり真面目に調査せずに唸ってたんですが、今回もう堪忍袋の緒が切れたので遅いテスト全部ぶっ○してやる!!!というつよいきもちで対応しました。
やったこと
というわけでやったことをまとめるけど、タイトルにある通りたぶんよくあるパターンじゃないです。
suiteがどうとかexampleがどうとかそういうテクニカルな話は1個もでないよ!!
まずは何が遅いのかを知ろう
まあrspecが遅いのはわかってたんだけど一応みてみましょう。
CIの設定は悪くないですね。完全にlintとtestが遅いですね。
じゃあrspecはどれくらいかと言うと、
ほとんどこいつやんけ!
じゃあrspecが遅いのはわかったしバシバシ直していきます。
とりあえず遅いテストを探そう
うーん、まあ確かに遅いっちゃ遅いのもあるんだけど、ずば抜けて遅いのがあるわけじゃないし、なんか全体的に遅そう・・・。
これは特定の遅いテストがあるのではなく、なんかやり方がおかしくて全体的に積み上げで遅いだけなのでは〜?
200を見るだけのfeature specをrequest specに
200を見るだけならfeatureじゃなくてrequestでよくない?という話になりまずこれを置き換えました。
個人的にこれ結構はやくなるんじゃないかな〜!と思ってたんですがもう何も変わらず。無風。
でもわかりやすさ的に画面いじったりしないならrequestでいいよねということでこれはこれで全部やりました。大変だったよ。
DatabaseCleaner、truncationじゃなくてtransactionでよくない?
もうね、結論からいうとこれ。
はやくなんねーなーと思ってspec_helper.rb
とrails_helper.rb
を眺めてたらなんか全部truncationでやってた 😨
これだけで10分短縮された。まさかここだとは思わなかった〜!
DatabaseCleanerは3つのクリーニング方法があって、truncate、transaction、deletionなんだけど、まあtransactionが使えるならそれが一番はやいよとは公式にも書いてある。
この辺とりあえずコピペで使っちゃってたから調べる機会ができてラッキー!
rspecよくわからないマンなんだけど、transactionとtruncationを切り替えながらテストを書くのが普通なんですか?
Capybaraと併用するときはtransactionだとコネクションが違うから、未コミットのレコードが読めなくて困るらしいです。
公式からコピペ。
config.before(:each, type: :feature) do # :rack_test driver's Rack app under test shares database connection # with the specs, so continue to use transaction strategy for speed. driver_shares_db_connection_with_specs = Capybara.current_driver == :rack_test unless driver_shares_db_connection_with_specs # Driver is probably for an external browser with an app # under test that does *not* share a database connection with the # specs, so use truncation strategy. DatabaseCleaner.strategy = :truncation end end
でもなんか弊社は平気だったな。弊社のテストだいじょうぶか?(これ絶対ダメなので別記事にします)
transactionにしたらここで躓いたよ
transactionにしたら速くなったしグリーンだしハッピー!ってわけじゃなかったのでそこだけメモっときます!
IDがインクリメントされていくのを考慮する
なんかファクトリで作ったレコードのIDを憶測して1とか2で見てるテストがあって、それはダメだでした。
transactionだとロールバックされた分のオートインクリメントは残るぽくて、そういうべた書きはやめてファクトリで作ったレコードのIDをちゃんと使うように変えました。
テストがランダムに落ちる
これ解決してないので僕の今日の仕事です。
あとたぶんまだまだはやくできるので、そしたらまた次の記事をかくぞ!