補習ほぼ確

学びや好きなことをただ自由に書く

テストは怖くない

GMOペパボ Advent Calendar 2019の10日目!の記事です。
qiita.com

テストコードについて、どう思いますか?
私は書くのがとても嫌い!!!!!!!
...でした。

それまでは精々独自バリデーションのテストくらいしか書いてこなかったのを Ruby on Rails での開発ライフを始めるとともにそのテストフレームワークとしてよく使われる RSpec を使い始めて、TDDの波に...乗るぞ...! と意気込んだものの、大苦戦してました。
いや、今もめっちゃ苦戦するけど。

テストをDRYにするとは?遅延評価とは?を何度も調べたり、
これはプログラミングなの???これはパズルでは???と何度も頭を抱えたり
「進捗は(実装は終わってるの!!でもテストが書けないので)無いです」と昼回で報告するばっかりだったりでものすごくテストコードを書くという行為が苦手でした。

そんな状態だったのが気が付けば......今では結構好きだしドンと来いよ!!的な勢いでテストに取り組めています。

どうしたらそうなったんだっけか。自分なりに何だかんだで好きになれてきた、克服するためにやったことをつらつら書いてみます。

1. とにかく小さな単位から切り出してテストに起こしてみる、テストファーストを意識

テスト駆動開発(TDD)はテストファーストな開発手法ですが、これに慣れてないので

  • 必要な実装を終わらせてからはじめてそれを Green にさせるようなコードを書く
  • 実装を完璧なものにしてからテストに取り掛かる

ということをやりがちでした。「必要な実装をすること」「テストコードを書くこと」を別々の工程に捉えているので、テストをいつも後回しにしてしまう。
そしてそこから実装に対しての全部のテストコードを書いて検証していこうとするので、テストが通らないとどこで間違えているのかの切り分けをするのも効率が悪い。どこまでを1つのテストで検証したいのか、テストする単位も見失いがちになる。
実装した内容を元にテストケースに起こしていくので、絶対に成功するであろうテストを書くことにしか目が向かず、検証すべき項目の見落としが発生する。
すっごい悪循環。。。。。

設計方針が固まったらすぐ実装に入るのではなく
まずはテストする項目を列挙する。
テストの対象(describe)、テストすべき特定条件(context)、テストで期待するアウトプット(it, example)といった具合に大きい粒度から落とし込んでみる。
思う通りにテストコードを組んでみて必ず失敗するテストを作成してから、一つずつテスト単位に合わせて実装する。
と取り組んでみることで、
もっとこのテストは簡潔に書けないか?もっとモジュール同士が依存しないように、実装部分を疎にできないか?ということにもより目が向けられるようになり、設計を見直す引き出しも増えました。

2. 詰まったら地道にデバッグすることから

テストどうこうでもないけど、見慣れないエラーを解読しても内容が分からない、どこが原因で失敗したか分からないとすぐ助けを求めていました。。
テストが失敗する原因はすぐに分からなくともデバッグはすぐにできるのでどんどんデバッグする。
まあ1をちゃんとやってたら「テストが失敗する原因がすぐに分からない」ということはないのですが。

3. 答えは基本ドキュメントに書いてある

マジでそのまんまなのですが、Capybara を使った E2E テストを書くとき中々思うようなマッチャでテストが通らないよ〜〜とよくベソかきました。ちゃんとドキュメントがあるならばそれを読めと...。

4. ペアプロでテスト→実装→テスト→実装を繰り返す

まだまだテストに対して苦手意識が高かったとき。
スプリントで速が出せていないよねというのをチームで振り返ったとき、
エンジニア歴/チーム所属歴が長い人短い人含めてチームで圧倒的成長をするためには、高速なフィードバックが必要になる。そのフィードバックを高速に回すための底上げしようぜ、とチームで意見がまとまり、ペアプロを導入しました。

  • ひとつのスプリントタスクをスクラムチームの一個人が受けるのではなく、チームで受けてチームで捌く
  • ペアプロをする2人は、1つのタスクに対して入れ替えていき、同じペアで長時間ペアプロを行わない
  • ナビゲータとドライバーは、1つの作業単位を終えた時点で交代していく

大まかなルールはこんな感じでやっていました。
qiita.com
こちらの記事にとても近いですね。
ここでやってみて面白かったのが、3つめの点を対象のテストを書く、テストの対象のコードを実装する、といった感じでテスト→実装→テスト→実装とナビゲータとドライバーを入れ替えてやったことでした。

この間最初にドライバー側(テストを書く)に回ったらしばらくテストを書くことに徹するので、そうなると当初は RSpec だけ書くのやだよ〜〜〜っていうかどう書けばいいかわからないのだが?????泣って感じなのですが、テストを書くことにもなんとか鳴らしていきつつ、上記のことも頭に覚えこませて進めていくと 1つの実装単位をペアで作り上げていくので認識のズレも1つ1つ解消していくことができてとても気持ちいい。

チームの誰とペアを組んでも1つのタスクを確実に仕上げられる、変化の強いチームができるし自分のこういう弱いところも無理やり引き上げることができるという「チームが成長する」という大きな目標達成の中で、副次的効果がたくさんありました。

===

克服した方法というか、振り返るととにかく書かなきゃ書けるようにならないな。というのがつまるところなのですが、自分自身に対して感じているだけでも以下が改善されてきたんじゃないかなと思っています。

1. 設計スキルが上がった
2. 機能実装で担保しなきゃいけない点を明確にして進められる
3. 「こうあるべき」への意識

あと、前の自分のようなあんまりテストを書いた経験がなかったインターンの学生さんに対してもテストの重要性を説いてまずテストから書こうぜ!って言って書いてる(...)

3については特に人力で品質担保はがんばらない!
サービスの品質と改善スピードを保つために、守るための環境を整えておくんだという意識がちゃんと自分の中でも持てるようになったなと。

テストコードがうまく書けるようになる、練度の高いテストを作り上げられるようになるのに
周りの人間がテストコードについて真摯にレビューしてくれること、チームがテストしっかり書くぞ!という軸をちゃんと持っていること、自分にとってはこの恩恵が大きかったなと思います。

「サービスとして、アプリケーションとしてどうあるべきか?」を常に考える、開発チームの土壌ができあがっている。
そういう土壌に身を置けるのはすごく幸せなことだなと思うし、だからこそ自分もその土壌を守るぞという意識が生まれる。
ひとつテストに取り組むことを通して、土壌の整え方に対する意識も以前と変わりました。

テストは怖く無い!!!テスト難しいけど、楽しい、難しいけどそういう再発見もあって楽しいよ。

===

めちゃめちゃお世話になりました。何度でも読み返したい。

www.slideshare.net


leanpub.com