TDDBC Sapporo 感想
2019-06-15、TDDBCに参加してきました。
とても深い学びと刺激があって、濃密な時間でした。
他の皆さんも言われてる通り、@t_wadaさんの基調講演のライブコーディングは本当にすごい。
公演全体がとても論理建てられていてわかりやすく、FAQへの回答を織り交ぜながらツボを抑えた構成で、全く中だるみしない、名言集のような2時間45分でした。
当日使われていたスライドはこちらです。
以下、雑ですが当日のメモをログとして残しておきます。
「テスト駆動開発」@t_wadaさん訳本
- 絶版からの約本。
- 失われてはいけない類の本というのがあって、これもその一つ。
- テスト駆動開発に必要なものはすべてこれに書いてあった。
- 読書会とかよりも実践向け
「動作するきれいなコード」
- 「テスト駆動開発」の巻頭の言葉より。
- 自分たちの能力を保管し、高める方法。
- 天才には不要。
- (MatzさんやDanKogaiさんのように)思考がそのまま降りてきてプログラムになる人はおそらくテストコードは不要。
- 凡人が天才と互角に渡り歩くための道具。
- 「I'm not a great programmer; I'm just a good programmer with great habits.」
- 「動作するきれいなコード」分割統治する。
- 「動作する」---> Red ~ Green
- 「きれいな」---> Refactor
アジャイルのよくある誤解「設計しない」
- これはありえない。
- なぜならプログラミングは「設計」だから
思考を紙にダンプする
- エンジニアがよくやること「箇条書き」
- これはそのままTODOリストになる
- これはつまり、その時の備忘録
- 改定し、実行する、をぐるぐる回しながらTDDを進める
10個のTODOリストを全部やるのではなく、一個ずつ「弱そうな」やつからやっつける
- テスト駆動開発では最初のターン、1個め2個めあたりが重たい
- ゼロの状態からイチの状態にするための諸々の作業があるから
- 環境依存の問題などが出やすいから
リファクタリングはプロダクトコードもテストコードも両方直していく
- Martin Fowler
- ソフトウェアの外部からの振る舞いを変えずに内部をきれいにするリファクタリングの手法を確立。
- Kent Beck
- テストコードもリファクタリングも両方一緒に行う。
きれいだけど動かないコードを極度に恐れてきたソフトウェア業界の歴史
- ソフトウェア業界の恐怖を象徴する言葉
- 「動いてるコードに触れるな」
- これに対して、いいからやるんだよ、は技術者のやることではない
- 度胸とか無謀では解決しない
- 動かなくなったことにすぐ気づくことができる仕組みがテストコード
TDDで一番大事なのはリファクタリング
- 「動作するきれいなコード」
- 「きれいなコード」に向かうための仕組みがリファクタリング
- ただ落とし穴がある
- 無限にできてしまうこと(きりがない)
- リファクタリングの脱出手段
- 時間の成約を設ける
- 深追いしない
- 重複がなくなることをゴールとする
- 2が1になったら終了、という目標を設ける
- 時間の成約を設ける
一番最初に失敗するテストを実行してみる
- スタートラインに立てているかをまず確認する
- 最小の手数で
- 予想もしない理由でエラーになることもある
- たとえばライブラリが入っていないなど
テストコードに日本語を書いていい状況なら、日本語で書く
- OSSや海外での使用が前提となっているプロダクトであれば英語での表記が必要となるかもしれない
- そうでなければ日本語で書くことをおすすめする
- なぜならテストコードはドキュメントだから
テストコードはプロダクトコードでテストし、プロダクトコードはテストコードでテストする
- プロダクトコードの欠陥を挿入する
- ミューテーションテスティング
- 後工程に行くほどテストコードの問題修正コストがかかる
- 投資対効果がもっとも高いのがこの一番最初のタイミング
テストメソッド間の依存関係が生じる前準備は信頼性を損なう
- 依存関係があるとテストコードを直列で実行する必要が出てくる
- テストコードは単体で動作し、前準備と後準備も単体で完結すべき
- JUnitで実行順序が順不同となっているのはそういう理由から
テストコードはエンジニアの調子に合わせて3段階のギアを使う
- 仮実装→三角測定→実装モード
- 最初の走り出しや慎重に進めたい時
- 仮実装→実装モード
- 通常の進め方
- 明白な実装モード
- 実装がイメージできて仕様が明確な時
数年経過して別の担当者がこのテストコードを観た時の視点で振り返る
- テストコードは具体的なTODOに落とし込んだ仕様に対して作成する
- 具体的な実装に落としたことで、抽象化された仕様が抜け落ちてしまった
- 当初の仕様レベルの備忘録としては存在していたはず
- テストコードを動くドキュメントとして捉えたときに、この抽象化された部分が存在しないため、後任者がテストコードを観たときに仕様を理解しにくい
テストコードの構造化
- ユニットテスティングフレームワークによってはネスト構造でのテストを作成できるので、構造化したテストコードを作成できると動くドキュメントとしての完成度が上がる
テストコードのメンテナンスコスト
- テストコードを自身をもって減らすことができるのは、作成した本人以外にない
品質保証の観点でのテストコード
- エンジニアの観点でのテストコード
- 動作確認レベルは最小限でよく、三角測定でよい
- 品質保証の観点でのテストケース
- 限界値、ペアワイズ等により網羅性を考慮する必要がある
パラメータライズドテスト
- 品質保証の観点でのテスト網羅性を解決する手段の一つ
- 一つのテストケースを複数のバリエーションで呼び出す
- インプットと期待値を構造体化して複数のバリエーションで繰り返し呼び出すことで、網羅性を担保する
- バリエーションごとにテストコードをコピペで量産する必要がない
まとめ・感想
僕がTDDに取り組み始めたのはたしかテスト駆動開発による組み込みプログラミング ―C言語とオブジェクト指向で学ぶアジャイルな設計を読んだ時だったので、2013年の頃だったと思います。
参画中のプロジェクトがC言語のシステム保守だったので、テスト駆動開発やアジャイルは遠い話と思っていたのが、この本に出会ってC言語でもテスト駆動開発ができることを知り、とても興奮したのを思い出します。
そこから独学でTDDを試し、プロジェクトに少しずつ導入をすすめていきました。
プロジェクトに導入する上でやはり苦労したのが、既存のやり方(デバッガによるステップ実行とエビデンス取得など)で得られると同等以上の品質を確保できることをどう担保するのかというところでした。
その頃のTDD文脈だと、TDDは開発者のためのものであって品質保証の観点とは分けて考えられていたと記憶しています。
品質保証の観点でエビデンスとするにはやはり既存の品質保証レベルを担保できると証明する必要があります。
命令網羅はカバレッジツールで確認できるとして、条件網羅、限界値分析の観点を担保するにはそれを考慮したテストケースを作成する必要があります。
するとテストコードが冗長になってしまいがちです。
今回の@t_wadaさんの講演では、その疑念を払拭するためのいくつかの方法が提示されていました。
一つは、テストコードを構造化することにより、動くドキュメントとしてのテストコードの完成度を上げること。
もう一つは、パラメータライズドテストを使うことにより効率よく網羅性を担保できること。
どちらもそれほど新しい概念というわけではなく、多くのテスティングフレームワークで実装済みなところからも、既に一般的な技術となっているのだと思いますが、やはり内に向かっているとそういう情報が入ってこないもので、その知見が得られたことも今回の収穫だなと思っています。
ペアプロでコード実装することの楽しさと集中度、効率の良さ(そしてドッと来る疲れ・・)を実感することができたのも収穫でした。
仕様の概念のとらえ方や、それに基づくメソッド名や変数名の付け方など、ほかの言語ペアのコードもとてもいい勉強になりました。
最後に、冒頭で@t_wadaさんがおっしゃっていたことですが、「テスト駆動開発」の書籍は読んで知見を広めるというより、自習向けの建て付けになっているので、実際に手を動かすことで理解が進んでいくとのこと。
テスト駆動開発はやってみてなんぼですね。
これからも精進します。