スピード感重視なのでテストは書かない。テストはなぜ開発を遅くするか

## あまりにバズってしまったので、前書きを追加

ここまでバズってしまって正直すまんかった。
この記事はもともと愚痴記事をマイルドにして投稿しただけなので「テストを勧める」とか「テストを信奉する」とかそこまで強い意図は特にありません。（私がテスト好きなのは否定しません）
「テスト書こう」に対して「そんなコストはない」と言いながら、いろいろ問題が生じる現状を愚痴りたかっただけです。愚痴るだけだと生産性がないから、なんでこんなに認識が違うんだろうと原因を考えた結果、テストを書くことに対する技術で実際にコストが大きく異なるなと気づいて書いた次第です。
この記事の対象は「テストを書く技術がなく、テストを書く気がない」組織に所属する人です。

[アジャイル開発において「テストコードは当然」なのか？](https://qiita.com/zaramme/items/f6b825c9b72b8eb9502b)という記事で（私の記事をきっかけとして）テストコードの「徹底」とか「カバレッジ100%」とかを批判し、トレードオフだ、という結論に着地したので、ちょっと私の記事に問題があったと反省しました。私はテストコードを徹底したことも、カバレッジ100%を目指した経験もありません。カバレッジで言うなら、80%くらいが理想だよねと思いながら、うっかり60%くらいになる、みたいなことが多々ある至って平凡なプログラマです。この記事もテスト無しでエンドレス障害対応するくらいなら多少なりとも書いたほうがいいだろ、程度の意図です。

テスト書かない組織に一石を投じられたのはいいけれど、ちょっと原理主義的に見えてしまったかな、という感じです。

尤も多くの人がテストの価値を軽視していると私が思っているのは間違いありません。

## 本来の「はじめに」

「事業立ち上げではスピード感重視なのでテストは書かない」という台詞をスタートアップでたまに聞く。上場企業でも「テストは割に合わない」と聞いた。

私の意見は「基本的にテストを書くべきで、テストがあった方が開発が早い」なのだが、どうも違和感があった。テストに対するコスト感が違いすぎるのである。

テストを書くことでそんなに開発が遅れるわけないだろ、と思っていたが、どうやらテストを書くと本当に遅くなるらしい。

テスト導入を推進する方の記事では、当たり前すぎて意外と語られないので、当たり前なことながら記事にまとめた。

追記: Twitterでご指摘があったのですが、この記事については少なくとも数ヶ月は稼働させる予定のプロダクションを想定して書きました。プロトタイプの段階では色々と異なる点があるため、本記事ではスコープから外します。また、私、フロントは全くわからないので、フロントでこういった内容が成立するかはわかりません。

## 三行で（更新）

* テストを書く習慣のある人とない人でテストコストの見積もりが大きく異なる。
* 理由は、テストありきの実装は比較的簡単に質の高いテストを書けるのに対し、テスト無視の実装にテストを書くのは至難の技だから。
* テストしやすい開発は技術力が必要。まずは先にテストを書くことから始めよう。

## なぜテストを書くべきか

テストを書くべき理由は軽く済ます。調べればいくらでも出てくる。

個人的には、フルタイムの技術的負債返済係をやった経験が大きい。開発という名目だったが、同僚も含め技術的負債返済と障害対応がほとんどだった。(余談だが、若手のうちにこういう経験をしとくと良い。生涯で書く恥ずかしいコードが格段に減る。逆に仕事を前に進めている感覚が持てないため自信を失うリスクもある)

「10行の変更を加えるためにすべてのソースコードを読み直す」という状況を経験すれば、誰だってテストを書くべきと思うはずだ。

## 「テストを書かない人」がテストを嫌い、テストのコストを高く見積もるのはなぜか

テストを書きたがらない人にとって(テストファーストの概念を知らない人にとって)、テストのコストは本当に高いから。
実装を先にしてしまった時点で、どんなに頑張ってもテストのコストは高い。障害対応係を雇ったほうがマシなくらい高い。
テストを書く前提で書かれないコードは書き直さないとテストを追加できない。

## 「テストを書く人」が、テストのコストを低く見積もるのはなぜか

テストファーストだとテストを書くコストが低いから。

「最終的にテストを書くコードである」という前提なら、テストを前提としないコードを書くメリットはほぼない。

## 要するに

私がいう「テストを書く」と、ダメなスタートアップ（製品の寿命を長めに想定しているのにメンテナンス性の向上に一切注意を払わないような企業）がいう「テストを書く」は全く意味が違う。

* テストを書く人にとってのテストはただの習慣であり、テストなしで開発するほうが遅くなることさえある。
* テストを書かない人にとってのテストは、すでに見かけ上は動いているコードの書き直しであり、二度手間である。

簡単に言ってしまえば、テストのやり方を知らければテストを書くのは難しい。テストを書く技術がなければ、当然テストのコストを高く見積もる。
テストの実力が足りなければ、テスト本を読めばいい。

## 実際のコストは

「コンフリクト頻発」とか「常時障害対応」とか「ソースコードが魔境で改変が命がけ」とか
テストがあればリソース半分以下で済むでしょう。
テストがないコードにテストを書くのは、気が遠くなるほど大変。というかほぼほぼリプレイスになる

## 追記:テストの品質について

Twitterでエゴサーチしたところ、2パターンでのテスト品質の違いについて記述が欲しいとのコメントがあったため、私の経験を追記します。

私の経験において、テストファーストでないコードに対し実装の変更なしでテストが書かれた事例はほとんど見たことがありません。そういったコードにテストを書いた経験がありますが、リポジトリ単位での結合試験より小さなものを書くためには、実装の書き直しが必要でした。(そういうコードは内部もおかしく、普通に書き直すだけで25%くらい性能が上がった)

以上より、「テストファーストでないコードのテスト品質」という観点は持っていませんでした。書けないので。

## スピード感ではなく本物の早さを求める新規開発がやるべきこと

* テストファーストを実践する
* 最低限テストを書く人を雇う
* 理由なくテストを書かない開発者に考えを改めてもらう

（ごく初期のプロトタイプにテストを書くかはいろいろ議論があるらしい）

## 追記:開発者がすべきこと

* テストファーストな実装
* テストを書きたがらない人への対応
* テストファーストがない、あるいはテストファーストでないコードに関する仕事を軽々しく引き受けない(おそらくその仕事は思っている以上に大変)

## 追記：テスト書きづらいなと思ったら

記事追加しといた。
[テストを書くかどうか議論するの不毛だから、どうやってテストを書きやすくするか議論しよう](https://qiita.com/aimof/items/419b9c20e73ba6e18a5e)

## まとめ

「テストを書く」の齟齬を解消しよう。
「テストを書く」の意味は私とあなたで全く異なる。

## 個人的ToDo

すでに生み出されて動いているレガシーコードにどう立ち向かうか

一応前に戦ったことがあるのでまとめておきました。

[すでに生み出されて動いているレガシーコード（テストのないコード）との戦争。結局武器はテスト](すでに生み出されて動いているレガシーコード（テストのないコード）との戦争。結局武器はテスト)

## 追加記事
[仕様変更に弱いからテストは書かない……？(´・ω・`)＜仕様変更を想定するならテストを書いてくれ頼む](https://qiita.com/aimof/items/849ded1293495d3bbb50)
[テストを書くかどうか議論するの不毛だから、どうやってテストを書きやすくするか議論しよう](https://qiita.com/aimof/items/419b9c20e73ba6e18a5e)
[すでに生み出されて動いているレガシーコード（テストのないコード）との戦争。結局武器はテスト](すでに生み出されて動いているレガシーコード（テストのないコード）との戦争。結局武器はテスト)