Slide 1

Slide 1 text

RSpec 導入奮戦記 2019/11/03 富山 Ruby 会議 01 #toyamark muryoimpl

Slide 2

Slide 2 text

とあるプロジェクトのお話 既存のRailsアプリケーションに対し、前任者が用意したRSpec coverage 5% の状態から、RSpec をほぼ実装したことのないメン バー4人とともに、学習しつつ、model, decorator, uploader, service のテスト, request spec, system spec を作成してリファク タリングするところまでやるぞ!という、Railsアプリの運用を楽しく しよう!とチャレンジをしている最中の物語。

Slide 3

Slide 3 text

ねらい ● テストを作成する文化を根付かせたい ● 本体コードが になっているので、リファクタリングして意図 のわかるコードにしたい ● 上記2つを通して、メンバーのスキルアップを図りたい

Slide 4

Slide 4 text

編成 ● メンバー 4 人 ○ RSpec ほぼ実戦では書いたことがない ○ 伸びしろ 100% ● 私 ○ コーチ ○ テストコードのレビュー ○ 難易度高いところをひたすらテスト書く係

Slide 5

Slide 5 text

現時点での計画 ● 機能のエンハンスは期間限定で停止 。 ただ し、調査・修正は実施する。 ○ なるべくテスト作成に力を注ぐため ● 本体をリファクタリングしたい欲をぐっと堪え てテスト作成に専念する 。 ○ 実行単位の難易度を下げる ○ いろんなところに波及しがちなのでテスト揃え てからやる ● 難易度を考え、model のテストから順に作成 していくこととする。 ○ テストのフィードバックが一番速いはず ○ 容易なメソッドが多かったため ① ② ③ 当作戦は3期計画を予定している。 ① model/decorator/uploader テスト作成期 ② request spec, system spec作成期 ③ リファクタリング期 ※現在 ① 期後半戦 (作戦開始後ほぼ1ヶ月)

Slide 6

Slide 6 text

実践編 その1 ● 当作成実行前に、モブプロ形式でテーブルに対応した ActiveRecord のモデルを 使ってブートキャンプを行う ○ データ作成で FactoryBot を使う、それを it/specify 内で使うために let を使う ○ User#full_name で “#{last_name}#{first_name}” に対して eq matcher を使う ○ .find で ActiveRecord::RecordNotFound が発生することを expect { … }.to で確認する ○ .find_by で be_nil を使う, allow を使って .find_by! 相当の挙動を and_raise で実現する ○ #save で change matcher, valid? 呼び出しに対し have_received matcher を使う ○ allow/expect は設定するobjectが検証対象のobjectと同一かどうか注意する ● 実戦前に rubocop-rspec を導入しておく ○ 既存のテストについては警告が大量に出るので除外し、テスト追加時に併せて対応する ○ コーチが指摘する量を減らし、その時間をより本質的な指摘に使うため ○ 警告食らってドキュメント見て Copの意図を理解してもらう狙いも

Slide 7

Slide 7 text

実践編 その2 ● モブプロ形式でモデルのテストを追加していき、その場でマージしていく ○ 2時間/日 を確保してもらって、ドライバを替えながら 対象 VS 私たち でテストに立ち向かう ○ 別件調査等でテスト作成の作業時間が確保できないメンバーもテスト作成、レビューができるように 会として設定している => 特にレビューが滞りがち ○ PR レビュー形式だとコーチがピンポイントで better な案を指摘しがち => テスト作成者たちが考え、議論することを重視 し、指摘はクイズ形式、解答は意図を添えて ○ モブプロ以外にも時間が確保できるメンバーは PR作成、質問をバンバンしてもらう ○ 出ているPRもこの時間でみんなでレビューして指摘、マージする ○ 実は他のコードをコピペしてきて解決しようとするのを抑止している ● コーチはひたすら事例を作成するようにテストを量産してレビューにまわす ○ 書き方のパターンを提供する ○ 新たなパターンが出てきた場合は、モブプロ時に紹介する ○ …ちょっと機会を奪っている気もする …

Slide 8

Slide 8 text

伝承編 これらのリンクを紹介し、一部説明を加えた ● RSpec によるユニットテストの書き方 - recompile.net ○ https://recompile.net/posts/how-to-write-unit-test-with-rspec.html ● RSpecのletを使うのはどんなときか?(翻訳) ○ https://qiita.com/jnchito/items/cdd9eef2ed193267c651 ● GETTING_STARTED.md - thoughtbot/factory_bot ○ https://github.com/thoughtbot/factory_bot/blob/master/GETTING_STARTED.md ● スペックのス ○ https://magazine.rubyist.net/articles/0021/0021-Rspec.html ○ https://magazine.rubyist.net/articles/0023/0023-Rspec.html ● 改めて学ぶ RSpec ○ https://magazine.rubyist.net/articles/0035/0035-RSpecInPractice.html ● Everyday Rails - RSpec による Rails テスト入門 ○ https://leanpub.com/everydayrailsrspec-jp

Slide 9

Slide 9 text

よく出た注意点 ● 振る舞いをテストすること。振る舞いのテスト != メソッドのテスト ○ carrierwave の store_dir のパス比較しても嬉しくない。動作させた上で store_dir に保存されること を確認したい ● use_transactional_fixtures, DatabaseCleaner, DatabaseRewinder 等の設定か ら example ごとにデータが削除 or ロールバックされているか確認する ○ この設定が入っているにもかかわらず、着手当初は手前の exampleで作成したデータが残っている こと前提でテストを書きがち。テストの独立性の話で --order rand と一緒にお伝えしておくのがよさ そう。 ● テスト作成をガイドするのもテスト ○ テストをどう書くかを悩むときにテスト流さずに机上で悩みがち。簡単に手元でテストが流せるから、 バンバン流してフィードバックもらって作っていって欲しい (願)。

Slide 10

Slide 10 text

はたして現状はどうなっているか (1ヶ月経過時点) ● メンバーはRSpec読み書きできるレベルには到達した ○ rspec-mock である処理を握りつぶしたり …を書くのはもう少し先の話 ○ 本体コード修正PRにもテストが付属してくるようになった ○ PRレビュー時に他のメンバーからもテストについて指摘が出てくるようにもなった ○ subject, let をうまく使った読みやすいテストコードが出てくるようになった ● 思ったよりテスト作成の速度が出ていない ○ 問い合わせによる調査、修正の時間が思っていたよりある。時間の確保が課題になった ○ 時間確保のため、モブプロ時間の内容の見直しや、作業の仕方を模索中。スプリントごとに施策を 替え、試してよさそうなものを採用するようにしている ● レビューに思ったより時間がかかる ○ テストの追加がクラス単位なので、クラスのメソッドが多いと PR が大きくなり、レビュアーの負担に なってきている => 適当な単位で区切ってはいるものの匙加減難しい

Slide 11

Slide 11 text

実感として ● 最初はモブプロ形式でみんなで進めて、レビューされ慣れたあたりで各自担当を もってテスト追加していく、くらいがよさそう ● メンバーのモチベーションが高いことに助けられている。 ただでさえ負債の回収フェーズでマイナスに気持ちになりがちなので、過度なプレッ シャーは取り除く ● まだまだ始まったばかりなので、コツコツ進めてリファクタリングに到達するぞ!

Slide 12

Slide 12 text

私からのお願い 頼む!アプリケーション書くときに テストコードも書いてくれ!!! 頼む!