LoginSignup
19
19

More than 5 years have passed since last update.

デスマの中でもTDDを貫いた話

Last updated at Posted at 2016-08-30
1 / 45

いきさつ

CDO「時間がないを言い訳にTDDが浸透しない」
俺「テスト・ファーストでないと実装できない体にしちゃえば、時間がなくてもやりますって」
CDO「それ、社内LTでしゃべって」

前世紀末「XP入門」のままのTDD原人のLT資料です。
※俺の環境:Java/JUnit/Eclipse/Gitlab


ネタ本

ケント・ベック
「XP エクストリーム・プログラミング入門
ソフトウェア開発の究極の手法」

和訳初版 2000/12 古い!


Test First

実装コードを書いて、そのテストをする
その順番をひっくり返す


1 今書ける一番簡単なTestCaseを一つ書く

  • Dao の CRUD なら Create から
  • 最初は実装もinterfaceもないから、compileもできない
  • 当然のことなので敗北感はない

2 IDE の quick fix で空classや空method作る

  • compile できた
  • それだけで なんか達成感 :smirk:
  • IDEに感謝。プログラマ黄金時代©Matz

3 Run Test - Red!

compile できたらすぐ Run Test.

  • 実装の中身なし Test Fail :broken_heart:
  • 当然のことなので敗北感はない

4 クソコード実装

最速最短でテストを通すためのクソコード実装

許す!

  • 即値のハードコーディング
  • コピペ
  • etc :poop:

5 Run Test - Green!

  • 最速最短でテストAll Green :green_heart:
  • なんて全能感 :smile:

6 local git に commit

  • TestCase 1つ
  • それを満足する最速最短実装コード
  • そして 1に戻る

テスト・ファーストまとめ

  1. 一番簡単なTestCaseをひとつ
  2. 空class, 空method
  3. Run Test - Red! :broken_heart:
  4. クソコード実装
  5. Run Test - Green! :green_heart:
  6. local git に commit して 1へ戻る

ドーパミンサイクル

メンタルに良い。

  • Redになっても敗北感なし
  • Greenになるたび達成感・全能感
  • 回転するたび脳内麻薬どんどん出ますよ :muscle:

「条件付け」

  • 実装が空で Run Testは無駄?
  • Red->Green でドーパミンを出す「条件付け」
    • 一度Redにしておく
  • Testをコピペしたまま手を入れ忘れて、いきなり Green というのもたまによくある話

JUnit画面でドーパミン 変態?

「条件付け」で自分の脳を改造する

  • Green画面 → 人生で最高の記憶を開く
  • 繰り返すうちに記憶操作を意識しなくてもテンション上がる
  • Plugin もあるかも
    • Green画面 → お気に入り画像がpop-upする
    • なければ作りなよ

だんだん簡単じゃなくなる?

  • 前回のドーパミンを燃料にブン回してさらに大きな達成感・全能感
  • ドーパミン・サイクル 良循環
  • TestClassのコードも組み合わせ可能なストックが蓄積していく

TestCaseレビュー

  • 推奨:サイクルをブン回して、一通り(ある程度)揃ったら、Testレビュー
    • WIP(Work In Progress)の Merge Request
  • 仕様理解が正しいか確認してから次のステップに
  • 実装のソースコードレビューはまだ先
    • 今はクソコードの山

リファクタリング

Testレビュー後、クソコードの山の実装を洗練

  • レビュー済みTestCase/TestCodeはFix。
  • 機能の等価性を保ったまま改修=リファクタリング
  • デグレ・リスク回避

1 一番簡単なRefactoring

一番簡単に「よりましな」実装コードにできることを1つだけ修正する

IDE の refactoring 機能で機械的に修正するのも1つ


よりましなコード

  • コーデイング規約
    • 最速最短コードとコーディング規約準拠は両立が◎
  • DRY原則(Don't repeat yourself)
  • リーダブルコード
  • アンチパターンにはまってないか

2 Run Test

  • Green? :green_heart:
    • 一番簡単なところだったのでたぶんGreen。
    • それだけでなんか達成感 :smile:
    • local git に commit して 1 に戻る

3 Test Red - Debug

  • Red? :broken_heart:
    • なんで?敗北感 :cold_sweat:
  • Debug
    • 1カ所だけの変更。簡単に原因はわかる
    • Greenに回復したら全能感 :smile:
    • 手をつけちゃいけないやつだったら、元に戻して1へ

リファクタリングまとめ

  • 正しいTestCaseが一揃い
  • 作業の方向性の正しさを確信
  • 1サイクル回すたびにコードが綺麗になる
  • 脳内麻薬どんどん出ますよ。 :muscle:
  • 予定工数を消化したら打ち切り
  • remote に push してCIへ

CI 継続的インテグレーション

  1. 開発branchにpush
  2. Jenkins で全体統合テスト
  3. All Green なら本流へのmerge request
  4. ソースコードレビュー

Don't say "lazy"

テスト・ファーストは、遅くないよね?

  • 初期は最速最短のクソコード
  • 予定工数内で可能な限りのリファクタリング
  • リファクタリング時間=0でも、要件を満たす実装は手中
  • CI通してればクソコードの山のままリリースする判断も可

中間まとめ

「テスト・ファーストでないと実装できない体」
 =脳内麻薬どんどん出してテスト中毒になったプログラマ

「軽い気持ちでいっぺん試してみなよ。みんなもやってるし。」:syringe::pill:


TDDの補足

元ネタがXP、エクストリームなので、いうことがいちいち極端です。

  • 今書ける(主観で)一番簡単なTestCase
  • (主観で) 最速最短でテストを通す
  • (主観で) 一番簡単に「よりましな」実装コードにできる

何から手をつけるか、どこまでリファクタリングするか、実際には高度な判断をしてください。
似たようなレベルだから手当たり次第にやることもあります。判断コストも含めての「一番簡単」


2013-01 某デスマのロードマップ

  • 2012-11-20 サービスイン
  • 2013-01-xx 初回請求
  • 2013-02-01 全額返金以外の通常退会、コンビニ払い
  • 2013-02-21 新規Web機能リリース
    • 「新機能は、お客様のご利用データが十分蓄積されてからのご提供となります。」
  • 2013-04-01 サービス仕様大改訂と同時に年度切替

ブリーフィング 

2013年1月から参加

  • サーバーのbacklogを一掃して
    • 契約系にうつる前任者の担当分
  • backlog はどこで管理している?
    • Redmine は個人レベル、プロジェクト運用なし
    • 口頭ベース
  • サービス外部仕様書 2012-07-02 こんなに古くて大丈夫か
    • 仕様書はもうついていってない。現物みながら

はじめの一歩

Checkout & Build
r14105 (12/28 09:59)
JUnit Runs:602
14:19 JUnit開始
15:22 終了 Errors:64 Failures:8

TDD原人は、project取得したらすぐに Run JUnit。


なんじゃこりゃ

  • 1h以上かかるだと!
  • 10%も Error
  • ひえー :scream:

状況把握

  • 実装javaに較べて*Test.javaが古すぎ
    • 最初は UnitTestを書いていたがメンテやめた?
  • AllTests.java の TestSuite発見
    • Runs: 171/171 Erros:15 Failures:0 所要時間20分
    • Error率は似たようなものだが、すべてが mail smtp
    • dummy の smtpサーバを教えてもらってAll Green
    • 生きているTestClassはこのSuite/SubSuiteで管理中

前任者の負担を小さく、プロジェクト状況をJUnitに聞く


CI欲しい

  • Run JUnit に20分以上 ローカルで毎回全部はリズムが悪い。
  • 特定の branch名を取得してテストを回し続ける環境が欲しい。
  • 所要時間の大半は、外部顧客管理サービスのレスポンス待ち。
    • それなら、マシン性能は低くても、所要時間に影響しない。
  • 仮想環境に、PostgreSQLと、smtp4dev入れて、Jenkins用branch にコミットしたら、自動テスト起動にしよう

CI環境構築

  • 2013-01-07 15:00 構築開始
  • 2013-01-09 10:41 JenkinsTest Green

新参者がやらかしてもこれで検出される。安心感


DBリバースエンジニアリング

実装担当の負担を小さく、DB状況をSchemaSpyに聞く


JUnit Debugで実装把握

生きているTestCaseをDebug実行して、内部実装を把握

  • 少しでもUnitTestがあったので、橋頭堡にして信頼できるところを広げていけた

当時の作業メモ

  • なんと BaseDao.java を使っていない。
  • 上記テストを実行しても BaseDao.java の factory では停止しない。
  • BaseDao.javaは 古いUnitTestのごく一部でしか使っていないということらしい。

Redmineプロジェクト管理

  • サーバータスクのRedmineチケット運用 2013/01/22~
  • 2013-02-01分 からRedmineロードマップで Todo管理

四半期評価 実績

  • 2/21 に新Web機能を追加対応込みで予定通りリリース。
  • 3/29 のサービス仕様大改訂を予定通りリリース。
    • 改訂内容は、当初企画案のMax以上まで実装
    • データマイグレーションで改訂前の蓄積データを扱うときも、ロジックの2本立てを回避

四半期評価 直属上司

  • 顧客側決裁権限者に商品をアピールできる機能にできた。
  • ○○自動選択の実現など当初の計画にはなかった機能も実現し、施策の効果を最大化した。
  • 平行してテストケースの作成も推進して頂き、今後の保守・メンテナンスコストの削減に貢献した。

追加要件も全部呑んでミッション・コンプリートです。


某プロダクト2016状況

  • 2013: Runs: 171/171 Erros:15 Failures:0 所要時間20分
  • 現在: 3,009個のテスト 所要時間47分
    • TestSuite管理はやめた。原則全部のTest.classがCIで走る
    • JavaScript も jasmine でTest. いくつあるんだ?

TDDの敵:状況依存

  • 特定の日時でないとテストできないケース
  • 特定のDB状況を前提にしないとテストできない
    • 例:あるTABLEの1年間の履歴から、次のアクションを決める
    • 対策1:setUp() の TestDataRegister()を頑張る
    • 対策2:フラグを立てるロジックとフラグを見て動くロジックに分離
    • 対策0:テストしにくい要件を、企画段階でDropして KISS(Keep It Simple, Sxxxxx)原則を貫く
  • Multi-Thread Timing

TDDの敵:遅い実装

  • ドーパミンサイクルの回転数が落ちる
  • 某プロダクトだと、外部連携顧客管理サービスのレスポンス待ち
    • 2013/07/24 Mock化
  • Springの動的Binding
    • 未解決

TDDの敵:必要のないテスト

  • ドーパミンサイクルの回転数が落ちる
  • 例: 該当者がいない古いタイプの契約のテストケース
  • 例: 境界条件でもないのに、無闇にパラメータ値のバリエーションでTestCase増やしている

TDDの敵:Test Red で帰る人

「明日朝自分が死ぬかもしれないと思ってpushしなさい」


TDDの敵:ラスボス

  • 実装を軽くみる風潮
    • 「機能設計だけして、実装は委託して。君は単価高いんだから」
    • 不倶戴天

最後に

  • CDOと各技術大臣はTDDの味方です。
  • ネタ本もトーカも古いので、最新情報はTDDBootCampとか外部リソースで追いかけて
19
19
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
19