※個人の見解です。所属する組織の意見を代表するものではありません。
未整理だけど一旦投下。
なぜ自動テストなのか(見えているゴール)
- よい自動テストはプロダクトの健康に大きく寄与する
- プロダクトの健康は開発者を変更の恐ろしさから解放する
- よい自動テストはシステムの継続的な運用コスト削減に寄与する
- 今更なに言ってんの?という話だが、固い組織の現状認識は想像を絶する
たくさんの壁がある
- 個人の壁
- 「自動テストなんて書いたことありません」
- 「妙な仕事増やさないでよ…」
- 組織の壁
- 「そもそもユニットテストなんて書いたら、大幅に工数増えるじゃん。それどうするの?そんな工数見積に載せられるわけないでしょ?」
- 「品質保証としてカバレッジの目標値どうすんの?ユニットテストというなら最低限C0カバレッジ100%だよね?」
- 「ユニットテストのテスト仕様に問題ないことは、誰がどうやって担保するの?」
- 「『俺も若いころやったことあるけど、テストコードがごちゃごちゃになってだんだん保守できなくなるんだよ』」
- 「『みんな通る道だよ、みんな一回はやってみて、失敗するもんだよ、自動テストなんて』」
- 受託開発の壁
- 「ユニットテストが効果を発揮するのは、長期的な開発が決まってるプロダクトだけだよね。1回だけの開発じゃペイするわけないでしょ?」
- 文化の壁
- すべてのプロジェクトで自動テスト書くなんて、コストメリット面から考えてあり得ない。という思い込み
- テスタビリティを考慮してプロダクトコード書いてる人がいない
- ある程度めんどうくさいとすぐに形骸化してやらなくなる
たしかに、よい自動テストを書くのはむずかしい
- アンチパターンの宝庫
- 丸腰で踏み込むとしぬ
- 自動テスト導入がそもそも大変なのに、さらにそれが失敗すると結構立ち直れない
少しずつ壁を崩す ← イマココ
- 固い組織では失敗しないことが大事
- 組織・開発者それぞれに小さな成功体験を稼がせる
- 組織・開発者に「自動テストはこれからコミットする価値がある」と思わせる
組織の壁の崩しかた
(個人の見解です)
###「この自動テストはユニットテストではなく機能テストである」と強調する
- ユニットテストや単体テストという表現をすると不毛な議論になりやすい
- 「全メソッド分の詳細設計書書いてレビューするんでしょ?」
- 「そんな工数どっから調達するつもりなの?」
- 「カバレッジ100%目指すんだよね?」
- 「プログラマが勝手に書いたテストコードなんて何のエビデンスにもならないよ?」
- 「全てのモデルクラスのpublicメソッドについてテストを書かないと品質がどうのこうの」
- いくらでも揉められる
- 「今まで面倒をかけて手でやっていた機能テストを、テストコードに置き換えるだけです」という論理はすこしだけ説得に寄与する
- 単体テストと違って、機能テストであればどんなプロジェクトでも必要性が認められる
- 「手でしこしこテスト仕様書を書いてテスト実施する時間でテストコードを書きます。コードさえかけば、実行は一瞬なので、工数は変わりません」
- 「コードのカバレッジは重視しません。なぜならこれは機能テストであって、機能テストの網羅性は従来と変わらないからです」
- 「工数は変わらず、機能テストの網羅性も変わらず、リグレッションテストの工数がほぼゼロになります」
組織として、最初の自動テストがこんな結果になれば上々
- 「自動テストを導入したのに、今までと開発コストが変わらなかった」
- 「コストが変わらず、手でやってた機能テストが自動化されたので、保守開発が楽になった」
継続しなければ意味がない
- 一時的にテストブームになっても、それが失敗したという体験が多いと、すぐやめてしまう。
継続するためにどうするのか
- 形骸化しないよう、小さなコストで最大限の効果が得られる施策から着手する
- 開発者が、自発的に自動テストを改善していきたいと思う環境作り
- 自動テストを書くのは普通のことなんだ、という意識づけをする
あらかじめ想定したアンチパターン
「プロダクトコードじゃなくてテストコードだし、ある程度コピペでいいよね」は許さない
- 仕様変更時にはコピペした箇所の分だけなおしが発生して超大変
- やっぱ自動テストはうまくいかないね、ってなる大きい要因
- 最低限、DRY(Don't repeat yourself)を保つ
- githubのロジック系の有名リポジトリが参考になる
- 高品質なテストコードは、コアとなるテストロジックが1つあって、各テスト項目はコアロジックに各種パターンのパラメータ引数を入力するだけになってる
「この見積工数はユニットテストを実施する工数です!」は通用しない
- 顧客に説明できないし、上司も納得させられない。
- 「そのユニットテスト、インプットは何?プログラマが勝手にやるの?クラスやメソッドの詳細設計書書いてレビューでもするの?すごい工数増えそうだよね!!」
「テスタビリティに配慮しないプロダクトコード」
- 状態遷移が複雑すぎる
- 高依存度、低凝集度
- 呼び出し順序に依存して動きが変わる
- プレゼンテーション層がビジネスロジックだらけ
「しばらく動かさないでいたら、テストコードの大部分が動かなくなってた。直すの大変…いつからこの状態なの…?」
- 自動テストを作っても、手で動かす仕組みにしてるとすぐ形骸化する
- 必ずCIで継続的に走らせて、フレッシュに保つ
「C0カバレッジ100%目指します」
- 異常系のテストがモックだらけになって作るのが大変。そのわりに、言うほど効果がない。仕様変更が大変になる
- 開発者は、明らかに重要ではないテストに多くの時間を割く体験をするため自動テストにコミットする意識が薄れる
- 重要というのは理解するが、自動テストをはじめてやる組織がいきなり目指すような目標ではない
UIの自動テスト
- 現状まだ世界中が模索していてベストプラクティスがないという認識
- やりたいのはやまやまだけど失敗するよりは、やらないでおく
いつか(5年後くらい)にたどり着きたいところ
- 「開発者はテストコードとプロダクトコードをコミットするだけの世界」
- プロダクトコードとテストコードを書けば、CI環境が自動的に検証してくれる
- いつでもフルテストができるから、保守開発によるデグレードがなくなる
- 開発者に手動テストをさせるとモチベーション面に起因して効率が落ちるが、テストコードを書かせると目がかがやく
- 開発者は創造的な作業に専念できる
- よりより機能の提案とか
- 細かいUIの改善とか
- 「コンピュータに仕事をさせるのがうまい集団」
- 自分達の仕事を自動化できないで、どうして他人の仕事を楽にできるのか?