Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
テストコードを導入して変わったこと 〜秘伝のタレ状態からの脱却〜
Search
uiui
November 24, 2025
1
150
テストコードを導入して変わったこと 〜秘伝のタレ状態からの脱却〜
2025年11月24日PHPカンファレンス香川にて
uiui
November 24, 2025
Tweet
Share
More Decks by uiui
See All by uiui
MCPを使ったRAGをPHPで作る
uiokuyama
0
57
レガシーシステムから学ぶ エラー処理との付き合い方
uiokuyama
1
160
Featured
See All Featured
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
26
3.2k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
16
1.8k
What’s in a name? Adding method to the madness
productmarketing
PRO
24
3.8k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
231
22k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
37
2.6k
Thoughts on Productivity
jonyablonski
73
4.9k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
46
2.6k
[RailsConf 2023] Rails as a piece of cake
palkan
57
6.1k
Scaling GitHub
holman
464
140k
A designer walks into a library…
pauljervisheath
210
24k
Fashionably flexible responsive web design (full day workshop)
malarkey
407
66k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
4.1k
Transcript
テストコードを導入して変わったこと 〜秘伝のタレ状態からの脱却〜 2025-11-24 PHPカンファレンス香川 @uiui
株式会社クレアヴォイアンス SWE エンジニア歴4年 自己紹介 uiui X: @U_Okuyama_Devlp work:最近はAWS/Laravel/Vue あたりでやっています。
また生成AI系をWebアプリの機能に組み込むみたいなのが 多いです。 それ以外:元々ヴァイオリン弾きです。最近は日曜音楽家と名乗ることにしました。 あと辛い物が好き!
皆さん、テストコードって どんなものだと思っていますか?
テスト書くの コスト高いよね? コストをかけられる人だ けが書くもの じゃないの? テストを書かないチームで抱きがちな印象
コストをかけられる人だ けが書くもの じゃないの? テスト書くの コスト高いよね? なくても動くから後 回しでいい? すごく高い信頼性を 求められている ものだけ?
テストを書かないチームで抱きがちな印象
コストをかけられる人だ けが書くもの じゃないの? テスト書くの コスト高いよね? なくても動くから後 回しでいい? すごく高い信頼性を 求められている ものだけ?
テスト書くより 実装を進めたい… 難しそう… 時間かかりそう めんどくさそう テストを書かないチームで抱きがちな印象
実際にテストコードを書いて思ったこと テストコードとは日々の開発を もっと “楽に・安全に・効率的に” 進めるためのものなのです
本日のアジェンダ ・テストコードがないプロダクト・チームに起きていたこと ・導入後に感じたテストコード /TDDのメリット・デメリット ・テストコード文化ゼロのチームにどうやって広めるか ・導入後に起きたチームの変化
今日話さないこと ・テストの書き方 ・テストコードの運用に関するベストプラクティス
今日知ってもらいたいこと ・テストコードがプロダクトやチームに及ぼす影響を知る ・チームにテストコードを導入する勇気を持つ
テストコードがない プロダクト・チームに起きていたこと
17~8年の歴史を持つ テストのない レガシーシステムのお話 (かつ独自フレームワーク )
$shipping = ($item->isFreeShipping()) ? 0 : 1000; if (!is_null($item->customShippingFee())) {
if ($user->livingInSpecialPlace()) { //特殊地域 if ($item->customShippingFee() + self::SPECIAL_PLACE > 3000) { //3000円以上だったら割引をする $shipping = $item->customShippingFee() + self::SPECIAL_PLACE - self::HIGHER_DISCOUNT; } else { $shipping = $item->customShippingFee() + self::SPECIAL_PLACE; } } else { $shipping = $item->customShippingFee(); } } if ($user->isPremium()) { if ($user->livingInSpecialPlace()) { $shipping -= 500; } else { $shipping = 0; } } *実際のコードではありませんが形はこんな感じ 🙃仕様の割にコードが長くて複雑 (ネストの深いif文もよく見られる) もっとスマートに書けるはずなのに どうしてこう書かれてるのかわからない
… $shipping = ($item->isFreeShipping()) ? 0 : 1000; if (!is_null($item->customShippingFee()))
{ if ($user->livingInSpecialPlace()) { //特殊地域 if ($item->customShippingFee() + self::SPECIAL_PLACE > 3000) { //3000円以上だったら割引をする $shipping = $item->customShippingFee() + self::SPECIAL_PLACE - self::HIGHER_DISCOUNT; } else { $shipping = $item->customShippingFee() + self::SPECIAL_PLACE; } } else { $shipping = $item->customShippingFee(); } } if ($user->isPremium()) { if ($user->livingInSpecialPlace()) { $shipping -= 500; } else { $shipping = 0; } } … 🙃責務や粒度が適切でないコード構造 メソッドに切り出さないがゆえに 複雑になってることも多々あり メソッドに切り出すべき …
… $shipping = ($item->isFreeShipping()) ? 0 : 1000; if (!is_null($item->customShippingFee()))
{ if ($user->livingInSpecialPlace()) { //特殊地域 if ($item->customShippingFee() + self::SPECIAL_PLACE > 3000) { //3000円以上だったら割引をする $shipping = $item->customShippingFee() + self::SPECIAL_PLACE - self::HIGHER_DISCOUNT; } else { $shipping = $item->customShippingFee() + self::SPECIAL_PLACE; } } else { $shipping = $item->customShippingFee(); } } if ($user->isPremium()) { if ($user->livingInSpecialPlace()) { $shipping -= 500; } else { $shipping = 0; } } … 時がたつと… 🙃どのパターンをテストすればいいかわからない
public function sendNotification(array $user, bool $isEmail) { … //メッセージの整形など様々処理 if
($isEmail) { // メール用処理 … mail($user['email'], "通知", $message); } else { // SMS用処理 … smsSend($user['phone'], $message); } … //メッセージ送信後の様々な事後処理 Log::info("送信完了: " . ($isEmail ? 'Email' : 'SMS') . "\n"); } 🙃共通化すべきでない処理の共通化
$invitation = Invitation::pending($id); //この時点で$idのInvitationはdone状態なので以下は通らないはず if (!is_null($invitation)) { $invitation->done(); } 🙃デッドコードの放置
当時悩んでいたコード現象まとめ 🙃仕様の割にコードが長くて複雑 🙃責務や粒度が適切でないコード構造 🙃どのパターンをテストすればいいかわからない 🙃共通化すべきでない処理の共通化 🙃デッドコードの放置 可読性も低く、どんどん拡張しづらくなる一方 (いつの時代のプログラミング …)
なぜこんなコードになってしまったのか
既存メンバーは色んな体験をしていた • 既存コードを修正して思わぬ箇所からバグが発生した恐怖 • 既存コードに手を入れるとテストコストが爆増 する • 使ってないはずのコードを消したらバグが発生
形成された文化 • 既存のコードはなるべく触らない • よっぽど自信のあるデッドコード以外は消してはならない • 機能拡張時は安全な付け足しコードが正義 になる •
テストをした後はコードを触って(改善して)はならない
形成された文化 • 既存のコードはなるべく触らない • よっぽど自信のあるデッドコード以外は消してはならない • 機能拡張時は安全な付け足しコードが正義 になる •
テストをした後はコードを触って(改善して)はならない つまり、リファクタリングができない!!
リファクタリングができない状態での開発
… $shipping = ($item->isFreeShipping()) ? 0 : 1000; … 事例①
*実際のコードではありません *むちゃくちゃ手続型でした 最初はシンプルだった
… $shipping = ($item->isFreeShipping()) ? 0 : 1000; if ($user->isPremium())
{ $shipping = 0; } … 仕様が追加されていく 事例① *実際のコードではありません
… $shipping = ($item->isFreeShipping()) ? 0 : 1000; if (!is_null($item->customShippingFee()))
{ $shipping = $item->customShippingFee(); } if ($user->isPremium()) { $shipping = 0; } … 仕様が追加されていく 事例① *実際のコードではありません
… $shipping = ($item->isFreeShipping()) ? 0 : 1000; if (!is_null($item->customShippingFee()))
{ if ($user->livingInSpecialPlace()) { $shipping = $item->customShippingFee() + self::SPECIAL_PLACE; } else { $shipping = $item->customShippingFee(); } } if ($user->isPremium()) { if ($user->livingInSpecialPlace()) { $shipping -= 500; } else { $shipping = 0; } } 仕様が追加されていく 事例① *実際のコードではありません
… $shipping = ($item->isFreeShipping()) ? 0 : 1000; if (!is_null($item->customShippingFee()))
{ if ($user->livingInSpecialPlace()) { if ($item->customShippingFee() + self::SPECIAL_PLACE > 3000) { //3000円以上だったら割引をする $shipping = $item->customShippingFee() + self::SPECIAL_PLACE - self::HIGHER_DISCOUNT; } else { $shipping = $item->customShippingFee() + self::SPECIAL_PLACE; } } else { $shipping = $item->customShippingFee(); } } if ($user->isPremium()) { if ($user->livingInSpecialPlace()) { $shipping -= 500; } else { $shipping = 0; } } … 現在に至る
public function sendNotification(array $user) { // メール処理 mail($user['email'], "通知", $message);
} 事例② *実際のコードではありません 最初はシンプルだった
public function sendNotification(array $user) { … //メッセージの整形など様々処理 // メール用処理 …
mail($user['email'], "通知", $message); … //メッセージ送信後の様々な事後処理 Log::info("送信完了: " . ($isEmail ? 'Email' : 'SMS') . "\n"); } 事例② *実際のコードではありません 例によって複雑化し
public function sendNotification(array $user, bool $isEmail) { … //メッセージの整形など様々処理 if
($isEmail) { // メール用処理 … mail($user['email'], "通知", $message); } else { // SMS用処理 … smsSend($user['phone'], $message); } … //メッセージ送信後の様々な事後処理 Log::info("送信完了: " . ($isEmail ? 'Email' : 'SMS') . "\n"); } 事例② *実際のコードではありません 仕様の追加により 切り出しや抽象化が必要になるが 変更できない
コードを改善しようとするも… 1. コードを変更する範囲が広いので、バグったときにどこが原因なのか探 る範囲も広くなる。 2. 各テストケースを手動でテストするため、開発中にこまめにテストすれば するほど時間がかかる 3. 開発者はサボりたくなる
&そもそもテストケースを網羅できている自信がないので、できるだけ変更範 囲を小さくしたくなる 付け足しにしよう /コード改善したくない という心理におちいる
負債が積み重なり、開発がどんどん重くなる • 属人化が進み、新人が参入できない • 仕様変更や追加が重い • 挙動が予想できない • 変更時のバグ混入率が上がる
コードはどんどん秘伝のタレ状態に …
設計の技量の問題?
設計の技量の問題? 共通化 SOLID原則 重複コード そもそも アーキテクチャが イケてなさすぎる 神クラス ALL手続型
それはたしかにあるけど
設計の技量の問題? • プロダクトを継続的にリリースしていく中で、チームがドメイン理解を深めていく ことも多い • 拡張性や柔軟性を最初から用意すると、コードは複雑になりがち。しかもその 拡張性は実際には必要にならないことも多い(=YAGNI) その時の要求を解決するシンプルな設計にしつつ その都度新たな要求に適合させたい
手軽にリファクタリングできる必要がある
どうやったら安全にコード改善ができるか?
リファクタリングを行うとき、 最初にすることは常に同じです。 対象となるコードについてきちんとしたテス ト群を作り上げることです。 (p.5) その後テストコードがある前提で話が進んでいく
テストコードとは?
function calcShipping(int $amount): int { // 3000円以上の購入なら送料無料 if ($amount >=
3000) { return 0; } return 500; } //3000円以上が送料無料になるか // ① 準備(Arrange) $amount = 3500; // ② 実行(Act) $shipping = calcShipping($amount); // ③ 検証(Assert) if ($shipping === 0) { echo "OK: 3000円以上は送料無料"; } else { echo "NG: 送料無料になっていない "; } ざっくり言うと 決めた入力を与え、期待した値になっているかを確かめるもの すごくシンプル テスト対象
テストコード(phpunit) $this->assertSame(0, calcShipping(3500)); 想像よりもっと手軽なもの
テストコードは難しい? ✖ テストコードを書くのは難しい 〇テストコードを運用するのは難しい (何に対して書くか・メンテナンス・実行スピード) 書いたことがない人からするとそのものが難しそうと思いがち
少しずつテストコードを導入
入社~現在 ・15年強の歴史を持つ テストのない レガシーシステム 2年前~ ・Laravelを使ったテストを導入した新規プロダクト 2年半前~ ・テストを導入した社内ライブラリ • まずは新規コードについて
1人で書いてみる
入社~現在 ・15年強の歴史を持つテストのないレガシーシステム 2年前~ ・Laravelを使ったテストを導入した新規プロダクト 2年半前~ ・テストを導入した 社内ライブラリ • 全体としてテストを書く運用にした •
TDDで開発してみた (このライブラリの開発は一人で行っていた )
入社~現在 ・15年強の歴史を持つテストのないレガシーシステム 2年前~ ・Laravelを使ったテストを導入した 新規プロダクト 2年半前~ ・テストを導入した社内ライブラリ • チーム全体でテストを書く運用にした •
CI/CDも整備した
テストコードのメリット
😎アクション一つでテストが実行できるので コードの改善を積極的に行える • 結果が期待通りかはテスト実行毎に保証されている • テストコードがあれば、最初は雑なコードでも大丈夫 • 改善する→テスト実行を繰り返してリファクタリングすれば 良い
😎テストケースが明確で誰でも手軽に実行できる • 実装に対して想定しているテストケースを残せている • 実行もできる • 将来変更する際にも何を検証すれば良いか明確
😎適切な粒度・責務の指標になる • 初めからテスト可能なコードを開発するためにもTDDでぜひ! • 前処理やテスト対象に対してのテストケースがやけに多い時に、 責務/ 粒度を疑うようになった
😎変更をする勇気を与えてくれる • これはもう絶対動くはず。と思って動かなかった経験、誰しもあるはず。 • 実行して結果を検証してないコードほど不確実なものはない • しかし、開発中編集のたびに書いたコードをすべてを通るような実行をし てるだろうか?(カバレッジ100%を推奨してるわけではない )
• 実はとても不安定な上で私たちは開発していた
システム変更の方法は、大きく 2つに分けることができます。 私はその方法をそれぞれ編集して祈ると保護して変更すると呼んでいます。 p.11 テストが期待した動作をすべて保証してくれている (もちろん書いたテストケースのみだが ) 😎変更をする勇気を与えてくれる
🧐デッドコードに対しては? • リファクタリングをすることでコードがクリーンに保たれ、デッドコードかどう かの判断はしやすくなる • ただしデッドコードを消してもテストが通ったからといって、それが正しいと は限らない • デッドコードだと確信を持つ機会を増やして積極的に消していこう
テストコードで解決できそうなこと 😎仕様の割にコードが長くて複雑 😎責務や粒度が適切でないコード構造 😎どのパターンをテストすればいいかわからない 😎共通化すべきでない処理の共通化 😃デッドコードの放置(一定の効果あり)
メリットはこれだけではなかった +TDDのメリット さらに生産性を高める
テスト駆動開発(TDD) 先にテストを書く →実装する→リファクタリング の繰り返し RED GREEN REFACT ARING 成功するコードを書く きれいにする
動作しないテストを書く
TDDで短期的にも効果があった *バグがないことを求められているプロダクト *少なくとも単一ファイル以上で管理するレベルのプロダクト (私の場合は実装時間は+15%くらい。リードタイムは減少。内部品質は良くなった)
TDDが短期的にも効果的な理由①
気づくと時間が溶けている作業マイベスト3 🥇デバッグ 🥈悩んでる時間 🥉テスト TDDが短期的にも効果的な理由①
気づくと時間が溶けている作業マイベスト3 🥇デバッグ 🥈悩んでる時間 🥉テスト TDDが短期的にも効果的な理由①
テストがない時の開発 (初心者) 2〜3行書く→デバッグ (ちょっと慣れた開発者 ) ほとんど書いてからデバッグ 一発で動いたらラッキー。 しかしほとんどの場合は、どこでバグが出てるのか調査に時間を費やす ことになる
🤓(だいぶ慣れた開発者) 数十行書く→デバッグを繰り返しながら開発する。 ある程度コードを書くと、デバッグしてバグが出た時に調査に時間がかかりそう だという直 感が働くようになる。 しかしデバッグにも時間がかかる のでバランスを意識し始める *個人的な所感によるものです TDDが短期的にも効果的な理由①
バグの 調査コスト (変更範囲に比例) デバッグ コスト (デバッグ頻度に比例) このバランスを取り始める
TDDが短期的にも効果的な理由①
しかしデバッグで それまでのテストケースを全て確 かめてるわけではない TDDが短期的にも効果的な理由①
コードの変更で、その前動いていた条件が 動かなくなることはよくあること 気づくのが遅いと結局、変更範囲が広くなる ↓ どこでバグってるか発見するまでに時間がかかる 対して… TDDが短期的にも効果的な理由①
😎開発しながらテストを頻繁に実行する 私はコンパイルするたびにテストを実行するようにしました。まもなく、生産性が大幅に向上したこ とに気がつきました。デバッグに時間がかからなくなっていたのです。 バグを入れ込んでしまっても、それまで書いたテストで検出できるため、テストを実行すればたちま ち発見されます。 〜 よってバグはたった今書いたコードの中にあるはずです。 〜 かつては見つけるのに1時間以上かかっていたものも、多くても
1〜2分で見つかります。 p. 90 TDDが短期的にも効果的な理由①
私はコンパイルするたびにテストを実行するようにしました。まもなく、生産性が大幅に向上したこ とに気がつきました。デバッグに時間がかからなくなっていたのです。 バグを入れ込んでしまっても、それまで書いたテストで検出できるため、テストを実行すればたちま ち発見されます。 〜 よってバグはたった今書いたコードの中にあるはずです。 〜 かつては見つけるのに1時間以上かかっていたものも、多くても 1〜2分で見つかります。 p.
90 最終的に実装も早くなる TDDが短期的にも効果的な理由① 😎開発しながらテストを頻繁に実行する
TDDが短期的にも効果的な理由②
気づくと時間が溶けている作業マイベスト3 🥇デバッグ 🥈悩んでる時間 🥉テスト TDDが短期的にも効果的な理由②
複雑な問題は考えることがたくさんあって 手が止まりやすい TDDが短期的にも効果的な理由②
対処法:仮説検証を早く回す TDDはインターフェースから考えることになる #[TestDox("要約の取得")] public function test_summary(): void { $frame
= new TextMessageFrame(text: TextMessageFrame::LINK_TAG . "Hello! Test!"); $expected_summary = "[リンク]Hello! Test!"; $this->assertEquals($expected_summary, $frame->getSummary()); } 先にメソッド名や引数・期待する戻り値などを決める その後中身を実装する TDDはインターフェースから考えることになる TDDが短期的にも効果的な理由②
対処法:仮説検証を早く回す TDDが短期的にも効果的な理由② RED GREEN REFACT ARING 成功するコードを書く きれいにする 動作しないテストを書く
対処法:仮説検証を早く回す 呼び出し方法・戻り値を 書き、どうなったら完成 なのか 一旦仮説を立てる 中身を実装してみる きれいにする もっと良い方法を 思いつく!
TDDが短期的にも効果的な理由②
😎考え込むのをやめて一歩ずつ前進する TDDが短期的にも効果的な理由②
他のメリット
😎テストにより使い方を示すことができる • 社内ライブラリにてドキュメントには大まかな使い方を書き、細かい書き方 はtestsディレクトリを見てくれと頼んだ • testの実行を通して利用者が使い方を習得することができた
😎TDDはインターフェースから考えることになる② • 「作るものは何か」から考えることになる • まず使いやすく・誤りにくいメソッドの外観を考える 習慣がつく(名前・入 力パラメーター・戻り値など) また、テストを書くことで実装よりも インターフェースに集中することに
なります(これは常に良いことで す)。 p.91 開発者はまず「作るものは何か」から始める べきだ。 〜 実装についての知識がシステムの他の部 分に漏れるのを防ぐ・コードの焦点を集中さ せられるし、カプセル化もできるようになる。 p.175
😎TDDのおかげでテストコードを書くときの モチベーションを高く保てた 設計:ユースケースを考え、システムの振る舞いを定義 テスト:振る舞いを確認する方法を定義
😎TDDのおかげでテストコードを書くときの モチベーションを高く保てた 設計:ユースケースを考え、システムの振る舞いを定義 テスト:振る舞いを確認する方法を定義 同じ方向を向いている • どちらも ユースケースの理解
が出発点 • どちらも 望ましい振る舞いの明確化 を行っている • 設計 ↔ テストのループで品質と理解が深まる
テストコード・TDDのメリットまとめ • リファクタリングができる • 想定するテストケースが残っている • 適切な責務・粒度の指標になる • 変更をする勇気を与えてくれる
• エラーを早期発見できデバッグ時間が短くなる • 仕様や使い方も示すことができる • TDDで着実に前進できるようになる • TDDでインターフェースをより意識できる • TDDでモチベが高い状態でテストコードを書ける
デメリット • 学習コスト →これはもうしょうがない。やってみるしかない。 • (テストコードを書く時間) →個人的には全体的には早くなったと思っている。最近はAIもあるし。 • テストコードの運用の難しさ
→テストコードも「コード」である
テストコード文化ゼロのチームに 広める道のり
最初に立ちはだかる壁 私たちも本当にテストを書くべきなのか?
Q.テストを書くべきプロダクトは? 1. バグがないことを求められている(少なくとも直さなくてはいけない) 2. バグが混入する可能性がある 3. ソフトウェアが今後も使用され継続的に開発していく必要がある
私は以下を満たすプロダクトはすべて必要だと思っている 自論
Q.テストを書くべきプロダクトは? 1. バグがないことを求められている(少なくとも直さなくてはいけない) 2. バグが混入する可能性がある 3. ソフトウェアが今後も使用され継続的に開発していく必要がある
私は以下を満たすプロダクトはすべて必要だと思っている 自論 多くのチーム・プロダクトに必要 (プロトタイプ等除く)
私の道のり
入社~現在 ・15年強の歴史を持つ テストのない レガシーシステム 2年前~ ・Laravelを使ったテストを導入した新規プロダクト 2年半前~ ・テストを導入した社内ライブラリ
step1: まずは1人で書いてみる
目的 • テストコードとは何かを知る • テストコードを書くのに慣れる • テストコードの意義を探る 知識と経験の間を行き来しながら 自分の理解につなげる
(補足)テストが書ける環境だったのか? この段階では • 自身のローカルだけでもいい ので書けそうなところを探す • 自身が書く新規コード があれば、テストを先に書きつつ実装すると良い •
関数に切り出されていて外部のAPI等に依存してなければ書けそう • プロダクションコードに影響はないのでチームメンバーもスルーしていた • DBの依存はあったが、とりあえずは後でデータも消すようにテストコードを書けば いいので試してみるくらいであれば問題ない
書ける気がしません • テスト駆動開発をやってみる • 全てのコードに書けなくても良い • 完璧を求めない。とりあえず書いてみないと始まらない
レガシーすぎます この本を読んで 一緒に頑張りましょう
そして、少しずつテストコードを書く 範囲を増やす
step2: テストコードを書くことを提案してみる
意識すること • テストコードで改善できそうな社内の課題実例を取り出す • 何が改善できるのか言語化する • 各メンバーがイメージしやすい話をすること • テストのpros/consを自分なりにまとめる
• 押し付けない、やってみようよのスタンス
step3: 導入をサポートする
意識すること • やることが決まっても積極的にサポートをしなければ廃れてしまう (人間は元の やり方で続けたくなるものだ) • 現状維持バイアス 的な意見が出ることも覚悟し、それを否定しない •
各メンバーがテストコードによる恩恵を自分で発見 できるように、サポートする (機会をつぶさない・誘導する) • 書くことで改善できそうな場面を見つけたら、すかさず&さりげなくサポートする
大事なこと 「他のメンバーは興味ない」「テキトーで平気」「やる気がないんじゃないか」と思うかもしれない 実際は、良い開発ができるなら誰でもやりたい チームは意外と 改善を望んでいる ただマインドや文化を変化させるにはエネルギーがいるし、リードしてくならなおさら あなたが一歩を踏み出すことで チーム全体のモチベーションが上がるきっかけになるかも
導入後に起きた変化
導入後に起きた変化 • 予期しないデグレを防げる確率が圧倒的に上がる →CI/CDなどに含めると、テストを必ず実行するのでバグの早期発見に つながる • リファクタリングができる、怖くなくなる
→コードに対する安心感が全然違う
導入後に起きた変化 • つまらないバグの修正時間が減る →バグを早期発見できるので、仕様・実装を思い出すコストが減る • きれいなコードが増える →テストが書きやすいコードは必然的に適切な責務・粒度のコードに
導入後に起きた変化 • 良い体験や流れは飛び火する →他のプロジェクトでも導入するかの話が出てくる
まとめ テストコードとは、 「バグがないかどうかを見つけるためのもの」 という枠を超えて 高い生産性を維持し、 継続的に進化できるプロダクトを支える仕組み であった
ご清聴ありがとうございました!