お茶漬けびより

"あなたに教わったことを、噛んでいるのですよ" 五等分の花嫁 7巻 「最後の試験が五月の場合」より

「TDD Boot Camp 2020 Online #1 基調講演/ライブコーディング 」を見た

見ながら Scrapbox に書いたことをここに貼り付けるだけのお仕事。

さすがに何度か見直さないと理解が追いつかなかった。

動画


TDD Boot Camp 2020 Online #1 基調講演/ライブコーディング

まとめた内容

f:id:pickles-ochazuke:20200801181734p:plain
TDD のサイクル

  • 最初に簡単な設計を行う

    • どこかに何かの形式で今考えていることを書き出す
      • 実装脳になると視野が狭くなる
      • レッド、グリーン、リファクタリングを繰り返していると何をしているか忘れるため
    • アジャイル開発では設計をしない」は間違い
      • 常に設計し続ける
      • 実装脳になってしまうので、現在の理解を書き出す
    • TDD においては、TODO リストを作る
      • 箇条書きで書き出す
        • 例えば、10 項目書き出したら全てをテストを書くわけではない
          • 動作するコードを書いてからきれいなコードを書くので、徹底的に問題を小さく分解して一つずつ解決していくやり方
      • 1 個最初に倒すやつを選ぶ
        • 選び方
          • 重要度から選ぶやりかた
          • テスト書きやすいものから選ぶやり方 TDDでは、最初はテスト容易性の高いものを選ぶ
          • することが多いので、最初に重要度のものを選ぶと作業が重くなる
          • テスト容易性の高いものと重要度が高いものは両立できる
        • 重要なものと簡単なもの
          • 重要なものと簡単なものは一致させることができる
          • テスト容易性と重要度の4象限
            • テスト容易性、重要度どちらも高いもの
            • テスト容易性、重要度のどちらも低いものに寄せていくことができる
  • TDDはテストファースト

  • リファクタリングのやめどき

    • 時間で区切る(何度でもチャンスはやってくる)
      • 5~10分
    • 数を数える
      • 重複している箇所を共通の関数に抜き出す
    • 一周するとたくさんのフィードバックがやってくる
      • 目標を考え直す(TODOリストを改定する)
  • ライブコーディング(https://youtu.be/Q-FJ3XmFlT8?t=2504

    • 面倒くさいと感じる
      • 問題が小さくない
      • 面倒臭いと感じる部分を分解する
    • 1-100まで
      • 1からnまで
      • あまり大事ではないのであとに回す
    • プリントする
      • 標準出力をテストするのは難しい
        • その割に効果が薄い
        • テスト容易性が低い
        • ビューのテスト
        • 壊れやすい
      • テスト容易性が低いので、あとに回す
    • 表現にブレがあるなら揃える
      • 大事なとこのみに集中できるようになる
    • 3の倍数のときは数の代わりにFizzにプリントする
      • プリントする部分はテスト容易性が低、重要度も低
      • プリントするを切り離し、変換するに変える
        • 重要で、テスト容易性が高くなった
      • 練習すればできるようになる
    • ただし
      • 準正常系
      • 例外系
      • 普通ではない振る舞い
    • 正常系
      • 1から100までの数をプリントする
        • 数を文字列に変換する
  • ライブコーディング前半(https://youtu.be/Q-FJ3XmFlT8?t=3376

    • 1周目と2周目は設計箇所が重い
      • なにもないところから始めるため
      • 設計の色合いが濃い
      • 名前空間やファイル名を考える
    • テストファイル名
      • テストは入れ子構造にできる
      • 対象クラスのテスト名にする
        • 対象クラス名+テスト
    • 一番最初はテスト環境がちゃんとできているか確認する
      • そのためにテスト失敗のコードを変更して、失敗することを確認する
    • テストコードは、動く仕様書であってほしい
      • 母語でテストコードを書く
      • プロジェクトに合わせる
    • テストコードの構造
      • 4フェーズテスト(3Aパターン(後片付けなし))
        • 準備(Arrange)
        • 実行(Act)
        • 検証(Assert)
        • 後片付け(言語によって必要)
      • 振る舞い駆動開発
        • Given
        • When
        • Then
    • テスト駆動開発では、下から書く
      • 検証がテストのゴール
        • ゴールは期待値
      • 軸をぶらさずにテストを書いていくことができる
    • プログラミングの手が止まる
      • できると思っていたのが、できない
      • すらすら行くと思っていたが、いけない
      • TODOリストに戻る(設計を考え直す)
      • 早く手が止まるほうがいい(あとになると取り返しがつかない)
      • テストは常に具体的になるので、なんとなくでは進めることはできない
    • TDDでは、抽象と具体をいったりきたりする
    • assertEquals は実測値と期待値がバラバラ
      • 最初に確認する
    • コンパイルエラーはレッド
      • レッドは設計の駆動力
      • 予想通りの失敗は悪くない情報
    • 作る前に使う
      • 作りやすいコードと使いやすいコード
        • 作りやすいコードより使いやすいコードの方が大事
        • 使いやすいコードは利用者から考えないと難しい
    • テストコードのテストはどうする?
      • ディフェクトインサーション(?)
        • わざと実装コードに判別可能な誤りを入れる
        • ミューテーションテスティング(変異性テスト)
          • プロダクトコードの中の機械的に変更可能な箇所を1箇所ずつ変えながら、テストを全件実行する
          • 全件すると時間がかかる(終わらない)
          • 実行コストがでかい
      • テストコードの実装に不安があるときにする
        • ベストなタイミング
          • 実装を変えるコストが一番小さいタイミング(コストが低い)でする
            • つまり一番最初にテストコードのテストをする
            • 仮実装
              • 茶番でテストを成功させにいく方法
              • テストのテストを先にするための方法
      • リファクタリングは実装から
        • コメントもリファクタリングの対象
    • ひどい実装
      • メリット
        • 設計に重きを置きたいとき
          • 実装に頭を使わないようにする
        • テストのテストのような厄介な問題を解決したい
      • デメリット
        • 実装がひどくなる(汚いコード)
      • 三角測量
        • 仮実装に対して、別の値を与えることでまともな方向に戻していく方法
        • テストを増やす
    • テストの増やし方
    • タスクの分割のスキル
    • [質問] 複数組み合わさったテストをしたいときは、そういうテスト用のメソッドを作るべき?それとも分解(のやり方)が間違っている?
      • 半分正解、半分不正解
      • 複数の値がまとめてアサーションしないと意味がないならば一つのアサーションという条件は解除して構わない
        • ゲッター2つまとめて見ないといけない場合とか
        • 戻り値と副作用同時に見ないといけない場合とか
      • けれど、まずは問題を疑う
        • 複数アサーションしないといけないのは、問題を上手く分解できていない
        • ドキュメントとしてのテストの体をなしていない可能性がある
      • ユニットテスト、スモールテストはテストの実行コストは考えなくていい
      • インテグレーションテスト、E2Eの場合
      • カスタムアサーション
        • ドメインの言葉でテストを書けるようになるのでおすすめ
    • テストを増やしてリファクタリングしたい状況が出たとき
      • 例えば、3箇所重複している箇所を発見した
      • レッドならリファクタリングしてはいけない
        • グリーンにする
          • アンドゥでテストを除去する
          • 今失敗しているテストを最短時間でグリーンにする
    • テストからログを出力するのは良くない
      • デモでは、テストの動きを確認するためにやっている
    • テストは、実行する順番が決まっていない

      • プログラマーがテストの実行順序に依存するようなテストを書いてしまうのを防ぐ
      • それぞれのテストが依存していないなら並列実行できるようになる
    • グリーンな状態を維持しながらリファクタリング

    • 仮実装は三角測量を通らないといけないルールはない

      • 実装者の不安レベルで間を挟むといい
    • テストの結果が予想通りなのはプログラマーにとっていいニュース

      • プログラマーのコンディションがいいので、思い切った実装にすすめる
        • テストや実装に不安がないのであれば大股で進めていい
          • 失敗した(レッドになった)なら謙虚に進める(仮実装や三角測量などを利用する)
        • 明白な実装
    • テスト駆動開発には、3つのギアがある(https://youtu.be/Q-FJ3XmFlT8?t=6817

f:id:pickles-ochazuke:20200801181817p:plain
TDD のスキル

  • [質問] 外部仕様、ストーリー、ユースケース、インプットとしてTDDで開発するときは、E2Eで開発するのがいいか? xUnitを使うときにテストファーストで書けない

  • ライブコーディング後半(https://youtu.be/Q-FJ3XmFlT8?t=7005

    • 月日が経ってテストコードのタイトルを見てみると具体的な振る舞いはわかるが、別のパターンの場合にどうなるか分からない
      • 次に何をしたらいいか分からない
      • テストコードの実装を見てみる
        • テスト対象がどうあるべきか伝わってこない
          • プロダクトコードを見に行かないと分からない
          • プロダクトコードにしか仕様が書かれていない
      • 動作するドキュメントになっていない
        • TDDはまだ終わっていない
    • テストコードをドキュメントにする
      • 具体レベルのテストコードで残すと仕様書にはならない
        • 実装するときはそれでもいいが、仕様書として残す場合、仕様レベルに直す必要がある
          • 仕様レベルの名称にする
            • 愚直なやりかた(言語によってはこれしかない)
              • テストコード名を長くする
                • 説明を仕様レベルと具体レベルの両方を書く
          • 階層構造に作っていく
            • 仕様レベルのツリー構造
              • ツリー構造をTODOリストと合わせる
              • 仕様の集合を分解していく
                • ドメイン理解をツリー構造やテストコード名に適用する
    • テストの数をなるべく統一する
      • テストの数の意味は、知らない人からは分からない
      • 三角測量で追加したコードは、いらなくなる(一時的なテスト)
        • メンテナンスコストになる
  • テストの構造化とリファクタリングhttps://youtu.be/Q-FJ3XmFlT8?t=8065

    • テストコードの約束の地
      • そんなものはなかった
        • テストのメンテナンスコストがかかる
          • テストはメンテナンスコスト
        • メンテビリティの低いテストコードが量産されている
    • 理解容易性が低いテストコードはメンテナビリティが低い
      • 読みにくいテストコードは癌になる
    • テスト駆動開発
      • プログラマーが気持ちよく書けるようにするのも大事
        • プログラマーの不安と自身の度合いに応じてテストを書けるので、生産を高める事ができる
        • ただし、TDDのゴールではない
          • プログラマーのコンディションの影響を受けているので、テストの粒度がバラバラになってしまう
      • 仕様として構造化とリファクタリングするのが大事
        • TDD(テスト)を行った本人が行う

f:id:pickles-ochazuke:20200801181847p:plain
まとめ

感想

大事な話が何個もあるので、たぶん時間が経つと忘れそう。

TDDの本を読んだことはあったけど、読んでいると自分の都合のいいように解釈してしまって、TDDはプログラマーが気持ちよく書けるようにするためのプラクティスなんだと少し思ってた節がある。ここで紹介しているように、テストコードが仕様として構造化されるとこまでリファクタリングするのがTDDだと説明していてTDDするときの姿勢を改めようと思った。といっても全然TDDできていないのだけど……。

仮実装や三角測量の話は、TDDの本読むだけだとあまり理解できなかったので、今回のライブコーディングで少し理解した気がする。

テストコードがあるコードでリファクタリングするとき、リファクタリング中はレッドになっていたので、今回の常にグリーンで進めていくのは勉強になった。今後は、グリーンを維持して書いていきたい。

仕事ではテストコードが必須ではないのでついプロダクトコードの実装から入ってしまって、どこかのタイミングでテストを書いたり書かなかったりするのだけど、やっぱりTDDを身に着けてTDDで実装を進めていきたいなぁと思い直した。

今回は話が濃いくてとても良いのだけど、TDDって何?ってのを知りたい人には長いかもしれない。そんな人は、以下の動画がおすすめ。こちらも同じ t-wada さんの講演です。

channel9.msdn.com

あとは、ここらへんもためになる(内容は組織に根付かせるとあるけど、個人でする場合も頭に入れておいたほうがいい話がある)。組織というか自分にテストの文化を馴染ませるために見てる。

組織にテストを書く文化を根付かせる戦略と戦術

リファクタリングする際、この本もためになるとコメントにあった(確か)。

コメント内容は忘れてしまったけど、ここらへんも紹介されていた。

t-wada.hatenablog.jp

テストとリファクタリングに関する深い方法論 #wewlc_jp

私にとってのテスト

http://xunitpatterns.com/~gerard/AgileSingapore2016-slides.pdf

講演ありがとうございました!!!