背景
スピード感重視なのでテストは書かない。テストはなぜ開発を遅くするか
の記事を拝読して、思うところがあったので、まとめてみる。
考察したい分類/内容
上述の記事の、以下の「まとめ」にはものすごく賛同できる。
「テストを書く」の齟齬を解消しよう。
「テストを書く」の意味は私とあなたで全く異なる。
齟齬が生じる一番大きな理由は、
各位の「前提事項」が全く異なるからだと考える。
一方で、途中の記事内容については、
前提となるプロジェクトの状態の考慮が少なすぎて、
人によっていろいろな解釈が生じてしまい、
賛同する人、しない人に分かれそうな印象であった。
「テストを書く理由」を主張する優れた人はいっぱいいる。
が、宗教的な信仰で神が居る前提で話が始まるように、
主張時に、「テストを書く」の意味は私とあなたで全く異なる
というどの点が異なるのかを相互に理解不足であるために、
「テストを書きたがらない人」と平行線のように交わらない。
本投稿では、どの点が異なると、
「テストを書く」ことへの意識が変わるのか、
プロジェクト/プロダクト/テストの性質を分類考察する。
例えば、テストを書かない人は、
こういう属性のプロジェクトの話をしているのかもしれない、
など想像をすることで、
テストを書く人へも、書かない人へも、
双方の主張のミゾを多少埋められるかもしれない。
プロジェクトの性質による違い
-
超少人数の新規構築タイプ
- リアルタイムで仕様が変わる
- 何らかのプロジェクト管理プロセスが不要なレベル
- 1~3人程度の少人数
-
中規模開発/アジャイル
- ほぼ全員コードが書ける/読める
- ピザ2枚が分け合える人数
-
大規模開発/ウォーターフォール
- 複数のレイヤーで役割分担
- 人数も多くスキルもバラバラ
⇒
大規模でもマイクロサービス化してアジャイルできるよね、
とか、分類していくとキリがないため、ざっくり3分類まで。
多くの人が最初に議論に挙げそうな観点はこの分類である。
しかし、「テストを書く」の意義を考える上では、
実はちょっと扱いにくい分類。
後述の分類に影響を与える場合が多いため、
この分類が「間接的に効いている」ため、
「テストを書く」議論がカオス化するのだと思う。
以降で、「テストを書く」の意義に
直接的に影響を与えている特性を検討してみよう。
既存コード有無(新規orメンテ)の違い
-
新規構築時
- テストを書く前提であれば、
後から書く意味はあまりないため、
テストファーストで構築していく、ことを想定する。
- この場合、テストを書くコストは低くなる
- テストを書く前提であれば、
-
メンテナンス時(既にテストの無い実装がある)
- テストファーストは実施出来ないため、
障害対応やメンテナンス時に、
少しずつテストコードを追加する、ことを想定する。 - この場合、実質的にはリファクタリングを伴い、
最悪全リプレイスになってしまうため、
テストを書くコストは高くなる。
いやいや長い目で見ればそのコストは回収できる、
などの議論を呼ぶこともある。
- テストファーストは実施出来ないため、
テスト対象/確認観点の違い(最重要)
-
BL(ビジネスロジック)やDB操作の単体テスト
- テストコードは作成しやすい。
- 適切に機能分割されているという前提ならば、
テストコードを書くべき、と最も主張出来る箇所。
-
UIや、PL(プレゼンテーション・ロジック)の単体テスト
- テストコードを作成しても、
人間の目で見ないとあまり効果がない場合が多い。 - 表示用のオブジェクト(HTMLのdom等)に想定通りの文字列が入っているか、
といった機械視点の確認まではテストコードで可能だが、
その表示上の位置、改行箇所が自然か?
的な確認は結局人がやることになり、議論が分かれるところ。
- テストコードを作成しても、
-
結合/連結テスト
- プロダクトの内容によって特性は大きく異なる。
最も議論が分かれるところ。
- UIの単体テストについても言えることだが、
例えば、「Selenium」などのブラウザ操作自動化ツールでの
「テストコード」について、議論に含めているのか除外しているのか、
人によって感覚が違うかもしれない。
- 「モック」や他の前提条件のエミュレートが、
どこまで容易/有効であるか、にも依存する。 - 機種/バージョン/環境依存の確認をここで実施したい場合、
「テストコード」だけでなく「テストコード実行環境構築」
が重要になってくる点に注意。
- プロダクトの内容によって特性は大きく異なる。
-
総合/システム/運用テスト
- 実データの豊富なバリエーションや、
特殊な操作時の例外挙動、性能確認、
複数の機種/ブラウザバージョン/複数環境での確認、
UIのレスポンス/操作感の確認など目的は多岐にわたる。
外部システムをモック化してしまっては意味が薄いため、
そもそもテストコードを書くこと自体が難しく、
テストコードだけでOKとは出来ない。
ここは、テストコードを書く書かないの、議論の対象外と考える。
- 実データの豊富なバリエーションや、
⇒
必ずしも「工程」の話をしているわけではない。
そのテストは「何のためにやるの?」という話。
例えば、作っているプロダクトの性質として、
「BL」部分が最も複雑で、その品質を確保することが重要であれば、
テストを書くことの、コスト対効果が高くなる。
一方で、「BL」はたいした処理が無くて、結合/連結以降の
品質確保が最も困難であるプロジェクトの場合は、
テストを書くことの、コスト対効果が低い、ということになる。
その他:影響しそうな要素
-
各担当者の「テストコード学習のコスト」
- 参加メンバーにどの程度のテスト知識があるか?
- Java,Python,Ruby,JavaScript.Swiftなどなど、
複数の言語を使っていると学習コストは上昇 - プロジェクトごとに使う言語が違うと学習コストは上昇
- SI案件では、自社サービスに比べ学習は実施しにくい、など。
-
プロダクトで使用している技術の性質
-
(開発チームにとって)新技術を使った開発か?
-
AIや分析案件、または性能が重要であるなど、
モノヅクリとしての性質がテストコードに向いているか? -
プロダクトに求められている「品質」の意味
- 主要な処理が動けばOK?
- 超レアケースも含めて一切のバグは許されない?
- どのくらいの寿命やメンテナンス頻度を想定?
- 例えば、あるゲームのチュートリアルを作る場合、
想定通りに動くことより、分かりやすくユーザが飽きないこと、
のほうが重要で、極端な話、実際のゲームと少し違う挙動でも良いし、
ゲーム本体が変わっても、必ずしもメンテする必要はない。
-
プロジェクトや企業の文化
- リファクタリングをどの程度許容するか?
- (最近は居ないと信じたいが)コードのステップ数で
生産性を見ているなどの習慣があるか? - 何の観点で工数見積を実施するか?
- カバレッジの評価に対する考え方
- テストケース表やレポートが納品物扱いになっているかどうか?
⇒
これらは、テストを書く書かないという以外にも、
「テストすること自体」や「テストを学習すること」
に対して、価値観が異なる可能性がある。
結論
誤解を恐れずにステレオタイプな印象だけで言えば、
「テストを書く人」のほうが技術レベルが高い場合が多い。
また、テストファーストのプロジェクトの方がバグが少ない。
そのため、「テストを書かない人」(及びそのプロジェクト)を
「遅れている」扱いしがちであり、
テストコード崇拝者やTDDの尖兵は数多く居る。
(なんでも絶対書くべきだ、的な人)
彼らの主張が間違っているわけではない。
ただし、上記で挙げた分類や考察のように、
テストを書くことで得られる費用対効果は、
プロダクトの特性、テスト対象によって、大きく異なる。
一方、「テストを書くと遅くなる」と主張する人は、
テストコードの費用対効果が高い箇所に目をつぶり、
テストコードの費用対効果が低い箇所ばかり見ている可能性がある。
また、そもそもテストを書いたことがない、
書き方を知らないなど、知識不足もあるかもしれない。
書く書かない、0か1か、みたいな二元論はやめて、
自分のプロジェクトの特性をよく見極め、
最も効果の高いところにはテストを導入し、
効果の低いところまで無理強いはしない、
ようにすれば、もう少し幸せな世界があるのではないか?
テストを書くことで得られる効果を実感しやすく、
また、部分的ならば導入/学習コストも低くおさえられる。
なぜこのプロジェクトでは
テストコードを書くべき or 書かないべき、なのか、
盲目的に「書く」「書かない」と主張するのではなく、
得られる効果と、書くためのコストを、
テストしたい要素ごとに考慮し、
個別特性に応じて考えていくべきである。
良いと思った側に「改善」していくことが望ましい。
レガシープロジェクトに対しても、
例えば「共通ライブラリ」のコードに対しては、
テストコードを導入してみよう、などの進め方。
そうした考慮の時の考え方の一つとして、
今回挙げた分類/考察が何かの参考になれば幸いである。
テストは目的ではなく手段。本来の優先度を考えて適した手段を採用したい。
おことわり
こういうポエム的な投稿をするのは全く本意ではない。
書いたそばから消したいくらい。
面白さに欠けている気がするし、
ストローマン論法のマトにしかならない。
ex.「俺、雨の日って嫌いなんだよね」
⇒「お前は干ばつで穀物が育たなくてもいいって言うのか?」
日本人は普段は曖昧なクセに、議論は極端に攻撃的。
こんなツマラナイ記事を読む時間があるならば、
こっちの記事でしりとりの考察を
読んでいただいたほうが多分面白いし、楽しい。
あくまでもいち個人としての見解を延べただけであり、
0か1かでは無いと言っているように、
「ここに延べた内容が100%正しい異論は認めない」
などと主張する気は全く無い。
全部にテストを書きたい人は書けば良いし、
書きたくない人はずっと書かないでいいと思う。
まとめ
「テストを書く」の「費用対効果」は
プロダクトの特性、テスト対象によって、大きく異なる。
0か1かの二元論はやめて、テストしたい要素ごとに個別に考え、
お互いの考え方を尊重しましょう。