Slide 1

Slide 1 text

テストオートメーションと 末長くお付き合いする ための 17 のこと XP祭り2024 家永英治

Slide 2

Slide 2 text

自己紹介 いえぴょん/家永英治 私とエクストリームプログラミングの出会い 2002年ごろ学生時代に平鍋さんのペアプロ帽子をネットで目 撃。楽しそうだなと思い門を叩いて、永和に運良く入社 2005年ごろに、チーム角谷にジョイン。twadaさんがTDDを含 めてXPコーチ。その時にテスト駆動開発のファンに 角谷さん、twadaさんがチームから卒業後、数年はメンテナンス 修正のメイン担当。途中慌てるシーズンもあったが、テストとと もにプロダクトを育てることの大事さを改めて実感 現在はペアプロコーチ、アジャイルコーチ。ペアプロやTDDを含 めてアジャイルの楽しさ嬉しさを伝えていくことを私のミッショ ンに https://www.agile-studio.jp/people/ienaga ペアプロコーチ アジャイルコーチ

Slide 3

Slide 3 text

私の経験詳細については、 健全なビジネスの継続的成長のためには健全なコードが必要だ』対談リンク集 (全6回) https://twop.agile.esm.co.jp/dialogue-about-healthy-code-to-make-business-thrive-continuously-6b13c8b344ac

Slide 4

Slide 4 text

今日のおしながき ● テストオートメーションの目的の再確認 ● あるある落とし穴 ● セーフティネットづくり戦略 ● 時間が余れば、JUnit Test Patternsの 弾丸特急読書会を開催

Slide 5

Slide 5 text

● 初めてテストの自動化に取り組む開発者 ● すでに取り組んでいるが苦労していることの 言語化に困っている開発者 ● テストに関わる技術的負債の知識を得たいスクラム マスター 想定参加者

Slide 6

Slide 6 text

テストオートメーションの 目的を再確認しよう Lessen 1

Slide 7

Slide 7 text

テストの目的は、 コスパ・タイパだけじゃなーい

Slide 8

Slide 8 text

1. コスパやタイパだけ でなく、ウェルパ大事 開発の嬉しい状態を保ち、 ものづくりに自信を持って主体的に参加し 続けるために(ウェルパ:ウェルビーイングパフォーマンス)

Slide 9

Slide 9 text

テストオートメーションの目的 ① 仕様をまとめるとき 期待する振る舞い(仕様の具体例)の会話を密にして理解を合わせるため Tests as Documentation, Tests as Specification、Expressive Tests, etc ② コード修正し、動作確認するとき 問題箇所をすぐ特定できるようにするため、セーフティネット、バグよけのため Defect Localization、 Tests as Safety Net, Bug Repellent, etc ③ 新たな要望が後から出てきても 自信を持って修正し、リリースし続けるため。変更に強いテスト! Robust Test, Simple Tests, Separation of Concerns, etc 参考にしつつ大きく再編成 ピックアップ

Slide 10

Slide 10 text

コミュニケーション促進のためのコード 「傍から見るとコードとドメインのどちらを議論しているのかわからない」とい うのは、ドメイン駆動のコードの成功を判定するひとつの基準になります。とあ る電子取引システムの仕事で私はそれを経験しました。あるとき、金融アナリス トが複雑な取引価格設定のロジックについて2人のプログラマーと話し合ってい ました。私は彼らが価格設定のルールについて議論していると思っていたのです が、実は画面いっぱいに表示されたコードを指差しながら価格設定のアルゴリズ ムの話をしており、コードの1行1行の読み方を話題にしていたのです! ここで は問題領域と解決空間のコードとの認知距離は構文上の記号だけだったというわ けです! - https://scrapbox.io/iki-iki/「たのしいコーディングのための"CUPID"特性」 “

Slide 11

Slide 11 text

(テスト)コードを使って ドメインエキスパートと開発者が 熱中しながら対話してつくる エクストリームプログラミング& ドメイン駆動設計が夢見る世界観

Slide 12

Slide 12 text

ワークショップの場合は 実例マッピング https://speakerdeck.com/nihonbuson/example-mapping

Slide 13

Slide 13 text

2. テストを使って対象ドメ インの理解の解像度をあげ ていこう

Slide 14

Slide 14 text

① 仕様をまとめるとき 期待する振る舞い(仕様の具体例)の会話を密にして理解を合わせるため Tests as Documentation, Tests as Specification、Expressive Tests, etc… ② コード修正し、動作確認するとき 問題箇所をすぐ特定できるようにするため。セーフティネット、バグよけのため Defect Localization、 Tests as Safety Net, Bug Repellent, ③ 新たな要望が後から出てきても 自信を持って修正し、リリースし続けるため。変更に強いテスト! Robust Test, Simple Tests, Separation of Concerns, etc.. テストオートメーションの目的 参考にしつつ大きく再編成 ピックアップ

Slide 15

Slide 15 text

複雑なドメインロジックの問題を シンプルなユニットテストを使って 紐解く 本当に大事な問題箇所をすぐに特定できる大事 UI バックエンド サービスA バックエンド サービスB 手動やEnd2Endテストに頼りすぎると、Slow TestやFlaky Testなどなど別の問題に 足を引っ張られ、ロジックの核心に辿り着けない 手動・E2E テスト 測定結果から ABC判定 ユニット テスト ネットワーク 通信エラーでたまに失敗 テストしたい 前提データの 準備操作が大変 非同期処理の要因 で、たまに失敗

Slide 16

Slide 16 text

手動テストに頼りすぎると、 デバッグ地獄や障害対応で 時間がみるみる溶けていく! (その結果=>「テストする時間がない」状態に入って、 ますますデバッグ地獄や障害対応に時間がみるみる溶けて、。。。の悪循環に)

Slide 17

Slide 17 text

End2Endに頼りすぎると、 Flaky TestやSlow Testで 時間がみるみる溶けていく!

Slide 18

Slide 18 text

3. 本当に重要な問題箇所を 特定し修復するまでの時間が 短くなるよう工夫を続けよう

Slide 19

Slide 19 text

① 仕様をまとめるとき 期待する振る舞い(仕様の具体例)の会話を密にして理解を合わせるため Tests as Documentation, Tests as Specification、Expressive Tests, etc ② コード修正し、動作確認するとき 問題箇所をすぐ特定できるようにするため、セーフティネット、バグよけのため Defect Localization、 Tests as Safety Net, Bug Repellent, etc ③ 新たな要望が後から出てきても 自信を持って修正し、リリースし続けるため。変更に強いテスト! Robust Test, Simple Tests, Separation of Concerns, etc.. テストオートメーションの目的 参考にしつつ大きく再編成 ピックアップ

Slide 20

Slide 20 text

筆者の経験から言うと、先輩から引き継いだコードには、リファクタリングが施 され、テストコードが仕様書の役割を果たし、プロダクションコードはドメイン 特化した用語で整理されていました。これらのおかげでコードの意図が理解で き、修正作業に自信を持って取り組むことができたのです。また修正箇所に不安 のあった大きなモデル変更に関しては、自らテストのセーフティネットを補強す ることで、前向きに開発を進めることができました。この話は「対談4」「対談 5」「対談6」でさらに詳しく話しています。 アジャイル開発において、ソースコードへの自信はとても重要です。この自信が なければ、理解不能なコードに対するイライラや、見落としやバグの恐れといっ た負の感情を抱えながらの作業が続くでしょう。 https://www.agile-studio.jp/post/twop-tdd-habitability “

Slide 21

Slide 21 text

アジャイル開発において、 ソースコードへの自信は とても重要

Slide 22

Slide 22 text

https://speakerdeck.com/twada/automated-test-knowledge-from-savanna-202406-findy-dev-prod-con-edition?slide=62

Slide 23

Slide 23 text

4.最大の効果は 「根拠ある自信」

Slide 24

Slide 24 text

5. テストを使ってリファク タリングを続けて、いつま でも自信を持って修正&リ リースできる状態を保とう

Slide 25

Slide 25 text

良いテストオートメーションの超簡易チェックリスト [1-5] テストコードは人が読んで理解できる 、会話を促進している [1-5] テスト失敗の際、エラーメッセージも何が起きたかわかりやすい [1-5] 準備や検証も含めフルオートメーションで実行できる [1-5] テスト結果は不安定・非決定ではなく、繰り返し実行できる、並列実行できる [1-5] テストはリファクタリングの耐性があり、めっちゃ助かる [1-5] 私は自信をもって修正&リリースできる。開発がたのしい (表明じゃんけんでチームで評価してみてね)

Slide 26

Slide 26 text

テストのあるある 落とし穴を抑えよう Lessen2

Slide 27

Slide 27 text

テストの不吉な臭い ● テストの不吉な臭いは、テスト オートメーションの落とし穴の 現象、原因仮説、対応方法をま とめたもの。xUnit Test Patterns ● リファクタリングの不吉な臭い のテスト版

Slide 28

Slide 28 text

Obscure Test(曖昧なテスト) 事象:テストコードを読んで何をテストしているか理解できない Fragile Test(脆いテスト) 事象:ちょっとした修正で、テストが壊れてしまい修復を強いられる。 リファクタリングの耐性が低い Erratic Test/Flaky Test(信頼不能テスト) 事象:テスト実行結果が非決定・不安定で、コード以外の要因によって GreenにもRedにもなる 押さえておきたい3つのテストの不吉な臭い

Slide 29

Slide 29 text

6. Obscure Test には気をつけよ!

Slide 30

Slide 30 text

7. Fragile Testに は気をつけよ!

Slide 31

Slide 31 text

8. Flaky Testに は気をつけよ!

Slide 32

Slide 32 text

Obscure Test(曖昧なテスト) 事象 ● テストコードを読んでも、すぐに理解できない 放置すると ● 読んで理解するまでの時間がかかり、メンテナンスコスト高&ストレスUP ● ドメインエキスパートとのコミュニケーション不全 ● 仕様の抜け漏れや矛盾に気づかずバグをリリースしてしまう 典型的な原因例 ● 1つのテストメソッドに多数のテストケースを熱心に書きすぎ ● テスト結果に無関係な情報が記載されすぎて、Arrangeのどの部分がAssertの結果に 関係しているかわからない ● 逆に謎の準備メソッドや巨大な共通フィクスチャが覆い隠しすぎて、Assertの結果 になる理由が読んでわからない ● モジュールの仕様や振る舞いではなく、実装詳細に依存したテスト https://www.agile-studio.jp/post/twop-tdd-obscure-test

Slide 33

Slide 33 text

9. 人が読んで理解でき る、対話を促進するテス トコードに書き換えよう

Slide 34

Slide 34 text

的外れなテストコードを 繰り返し自動実行し、Greenになっても ユーザの期待通り動くこ とはない

Slide 35

Slide 35 text

ドメインに詳しい人と、 対話を重ね ユーザニーズを捉えた 仕様の具体例 を 実行可能な仕様( つまりはテストケース) として簡潔明瞭に記述し、 継続的に検証し続ける が大事

Slide 36

Slide 36 text

10. POやドメインエキス パートと会話している時、 すでにテスト活動は始まっ ている!

Slide 37

Slide 37 text

私も過去、テストを書いて実 行に熱中するあまり、 会話を疎かにして、痛い目 に 会う苦い経験あり

Slide 38

Slide 38 text

DevOpsの継続的テストなら、 いつでもどこでもテスト https://danashby.co.uk/2016/10/19/continuous-testing-in-devops/

Slide 39

Slide 39 text

テストを読みやすく対話しやすくするポイント ● テストクラスやテストメソッドに日本語を使うなど、人が読むものと して扱う ● 1つのテストメソッドでは1つの観点に絞ってテストする ● 技術語彙よりもドメイン語彙を使う、テストは実装詳細(How)で はなく、 仕様ー振る舞い(What)にフォーカスする ● Arrange Act Assertの記述では、In-Outの変数の因果関係がすぐに わかるように工夫する ● どうしてもコードで表現しきれないなら、コメントで補足する ● etc…

Slide 40

Slide 40 text

Obscure Testの典型的な原 因例や対処に関しては次のブ ログを参照 https://www.agile-studio.jp/post/twop-tdd-obscure-test

Slide 41

Slide 41 text

Fragile Test(脆いテスト) 事象 ● 機能修正やリファクタリングの際に多数のテストが意図せず失敗し、修復を強いられる 放置すると ● 意図せず失敗したテスト修復に時間がかかり、 メンテナンスコスト高でストレスフルな開発(コスパ&タイパ&ウェルパ悪化) ● リファクタリングを妨げるテストで、だんだんと負債を増やし、修正の自信を喪失 典型的な原因例 ● テストコードが実装詳細に密結合。インタフェースと実装の分離が不十分 ● =>UI のEnd2Endの場合は、テストコードがUIの実装詳細に触れすぎる ● =>モック利用の場合は、モックがテスト対象の詳細に触れすぎ ● 複数のテストケースが共通のフィクスチャ依存で互いに影響し合う。テストの独立性不足 ● etc https://www.agile-studio.jp/post/twop-tdd-fragile-test

Slide 42

Slide 42 text

大抵はテストコードやモックがテスト対象に横恋慕 https://www.agile-studio.jp/post/twop-tdd-fragile-test ※「特性の横恋慕」 書籍リファクタリ ングで紹介された不吉な臭いの一種。 モジュールAがモジュールBに ちょっかい出し過ぎて密結合のアンチ パターン

Slide 43

Slide 43 text

11. テスト書く際も 疎結合は大事!

Slide 44

Slide 44 text

Fragile Testの原因と対策に ついては次のブログを参照 https://www.agile-studio.jp/post/twop-tdd-fragile-test

Slide 45

Slide 45 text

私も過去にモックスタブの箇 所で脆いテストに悩まされた 経験あり

Slide 46

Slide 46 text

Erratic Test/Flaky Test(信頼不能テスト) 事象 ● コード以外の要因でテスト結果が非決定・不安定(RedにもGreenにもなってしまう) 放置すると ● テストのリトライや失敗原因の特定に時間がかかり、メンテナンスコスト高でストレスフルな 開発環境 (コスパ&タイパ&ウェルパ悪化) ● チーム内外でテストに対する信頼性が喪失してしまう由々しき事態に! 原因 ● ネットワークや外部サービスなど環境依存で結果が変わる ● 非同期処理の箇所で、待ち時間などで結果が変わる ● 並列処理の箇所で、実行タイミングなどで結果が変わる ● 複数のテストで共有されたデータやファイルが干渉し合って、 テストの実行順序によっては結果が変わる ● 実行の時間やランダム要素で結果が変わる ● リソース枯渇のタイミングで結果が変わる ● etc…

Slide 47

Slide 47 text

信頼不能テストは、 原因特定がやっかい!

Slide 48

Slide 48 text

Redの原因が たまたま失敗なのか 重大なバグなのかの判別も やっかい!

Slide 49

Slide 49 text

https://speakerdeck.com/twada/automated-test-knowledge-from-savanna-202406-findy-dev-prod-con-edition?slide=5

Slide 50

Slide 50 text

人類が テスト結果を信じなくなる 危機的状況! 主語がでかくなりすぎた > <

Slide 51

Slide 51 text

日頃の事前予防や発生してからの対策は 日頃のFlaky Testの予防策としては ● 信頼不能テストを招きがちなEnd2Endテスト(Largeテスト)を減らす。 ネットワーク通信や外部サービスや非同期処理や共有されたファイルアクセ スなしでテストする範囲を増やす。 ● ランダム要素、実行時間など信頼不能につながる箇所に強く依存したコード 減らし、繰り返しテスト可能になるように設計改善 ● DBアクセスありのMedium Testの作戦を取る場合は、トランザクションロー ルバック、不変のFixture、データorスキーマorデータベースを隔離して独 立性を上げる、適切な知識をもって対策を施す 発生してからは、 ● 実行結果が不安定なテストを隔離や混入タイミングを調べ、原因を特定する

Slide 52

Slide 52 text

データベースありのテストの際は、対策を忘れずに https://www.agile-studio.jp/post/twop-tdd-erratic-test 前提のフィクス チャを隔離して 共有しない 状態不変の フィクチャ ロールバック等で 必ずクリーンアップ

Slide 53

Slide 53 text

12. Flaky Testだらけ状態 に陥らないために、日頃か ら予防的処置に取り組もう

Slide 54

Slide 54 text

効果的なテストの セーフティネットのあり方を 再確認し、更新しよう Lessen3

Slide 55

Slide 55 text

実践アジャイルテスト: テスターとアジャイルチームのための実践ガイド

Slide 56

Slide 56 text

13. ユーザビリティテスト、 探索的テスト、非機能要件の テストなどを忘れずに

Slide 57

Slide 57 text

参考:https://testing.googleblog.com/2010/12/test-sizes.html 参考 Googleのソフトウェアエンジニアリング Large Medium Small

Slide 58

Slide 58 text

14. Large、Medium、 Smallなど言葉の理解をチー ムで揃えよう

Slide 59

Slide 59 text

No content

Slide 60

Slide 60 text

15. Large Testを少なめに Small Testを多めにしよう

Slide 61

Slide 61 text

注意のチェックリスト ❏ 実行結果がGreenにもRedにもなり、非決定・不安定である ❏ テスト実行結果が出るまでに時間がかかる ❏ テスト失敗時に問題箇所の特定までに時間がかかる ❏ 失敗した理由を特定したはいいが、非同期処理のテストの書き方などが原因で、 テスト対象の問題ではなかった … ❏ End2End(Large)テストの失敗原因特定と対処で メンテナンスコスト高が発生している ❏ ステークホルダーやエンジニアの間でテスト結果に対して信頼が 喪失している (チームで評価してみてね) もしも、現在End2Endテストが多めの場合

Slide 62

Slide 62 text

注意のチェックリスト ❏ スタブ・モックが実装詳細に触れすぎて、対象モジュールの 期待する振る舞いをテストコードを読んでも理解できない ❏ スタブ・モックが本物と差異が発生してしまい、本来テスト結果がRedになるべ きところでGreenが発生している ❏ リファクタリングの耐性が低く、意図せずテストが失敗し、修正が必要。テスト がリファクタリングの阻害要因になってしまっている ❏ 機能修正の際に、意図せずテストが失敗し、修正が必要 … ❏ スタブ・モックの箇所の理解や修正で、メンテナンスコスト高&ストレスUPが 発生している (チームで評価してみてね) もしも、現在スタブ・モックが多めの作戦の場合

Slide 63

Slide 63 text

私も過去にモックスタブに頼りすぎ たSmallテストを捨てて、自信を 持ってリリースできるように後から セーフティネットを調整した経験あ り

Slide 64

Slide 64 text

16. 現状を評価し、嬉しい テストのセーフティネット のあり方をチームで話し合 おう

Slide 65

Slide 65 text

もしも、市場でバグ発見が 頻発しているなら

Slide 66

Slide 66 text

後から発見したバグは、本来は何によって補足するの がよかったのだろうか? ● 市場障害による損害は許容範囲内と判断する? ● リリース直前のまとめての手動テストでカバー? ● End2EndのLarge Testでカバー? ● 外部サービスには接続しないが、DB接続して確認す るバックエンドのMedium Testでカバー? ● ドメインロジックにフォーカスしたバックエンドの Small Testでカバー? ● etc… (チームで評価してみてね)

Slide 67

Slide 67 text

17. バグを直すだけでなく テストのセーフティネット も直そう

Slide 68

Slide 68 text

何を検証したい?どのテストを使って検証したい? 例: A: 複数マシンでUIからDB、外部サービスAとも 連携するEnd2End。 (Large Test) B: フロントエンドの表示用モジュール(Small Test) C: バックエンド。特にDDDでいうところの集約 (Small Test) D: バックエンド。特にWebAPIのリクエストから DBを介してレスポンスまで。ただし外部サービス 連携はモック・スタブを使用 (Meduim Test) … ページ WebAPI-B WebAPI-A コンポーネント 集約 A B C D

Slide 69

Slide 69 text

まとめ

Slide 70

Slide 70 text

今日のタイトル: テストオートメーションと 末長くお付き合いする ための17のこと

Slide 71

Slide 71 text

1. コスパやタイパだけでなく、ウェルパ大事 2. テストコードを使って対象ドメインの理解の解像度を あげていこう 3. 本当に重要な問題箇所を特定し修復するまでの時間が 短くなるよう工夫を続けよう 4. 最大の効果は「根拠ある自信」 5. テストを使ってリファクタリングを続けて、いつまで も自信を持って修正&リリースできる状態を保とう 6. Obscure Testには気をつけよ! 7. Fragile Testには気をつけよ! 8. Flaky Testには気をつけよ!

Slide 72

Slide 72 text

9. 人が読んで理解できる、対話を促進するテストコードに書き 換えよう 10. POやドメインエキスパートと会話している時、 すでにテスト活動は始まっている! 11. テスト書く際も疎結合は大事! 12. Flaky Testだらけ状態に陥らないために、日頃から 予防的処置に取り組もう 13. ユーザビリティテスト、探索的テスト、非機能要件のテストなど を忘れずに 14. Large、Medium、Smallなど言葉の理解をチームで揃えよう

Slide 73

Slide 73 text

15. Large Testを少なめにSmall Testを多めにしよう 16. 現状を評価し、嬉しいテストのセーフティネットのあ り方をチームで話し合おう 17. バグを直すだけでなくテストのセーフティネットも直 そう 3つだけ選ぶなら

Slide 74

Slide 74 text

2. テストを使って対象ドメ インの理解の解像度をあげ ていこう

Slide 75

Slide 75 text

5. テストを使ってリファク タリングを続けて、いつま でも自信を持って修正でき る状態を保とう

Slide 76

Slide 76 text

16. 現状を評価し、嬉しい テストのセーフティネット のあり方をチームで話し合 おう