Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ユニットテストの現場の問題を原則に立ち返って考える / think deep unit test practical problem

ユニットテストの現場の問題を原則に立ち返って考える / think deep unit test practical problem

PHPカンファレンス福岡2019 ( #phpconfuk )で発表するユニットテストの現場の問題についての整理を行っていくトークです。

Kazuki Higashiguchi

June 29, 2019
Tweet

More Decks by Kazuki Higashiguchi

Other Decks in Programming

Transcript

  1. © - BASE, Inc. . 問題を考えるための基礎となるユニットテストの ⽬的 . 現場の問題の整理‧問題に対する戦略の選択肢 .

    テスト戦略に対するメリット‧デメリットの評価 このトークが提供すること
  2. © - BASE, Inc. このトークの流れ . 取り上げる現場の問題 . ユニットテストの⽬的 .

    現場の問題の整理と評価 . まとめ . 参考‧引⽤資料
  3. © - BASE, Inc. : @hgsgtk ⾃⼰紹介 東⼝ 和暉 (

    Higashiguchi Kazuki ) Backend Engineer (Go, PHP, Python etc) BASE BANK, Inc / Dev Division
  4. © - BASE, Inc. このトークでの問題整理フォーマット 現場でのユニットテストの問題 問題 障害 戦略 その課題の難しさ‧取り組みを妨げる障害

    障害に対してどのような戦略‧戦術を⽤いるか 判断 評価 . 戦略のメリット . を評価する . 戦略のデメリット . を評価する
  5. © - BASE, Inc. 我々を取り巻く様々なテスト • 受け⼊れテスト • 機能テスト •

    統合テスト • ユニットテスト • 負荷テスト • コード品質テスト • etc
  6. © - BASE, Inc. ユニットテストとは • プログラムを構成する⽐較的⼩さな単位(ユニッ ト)が個々の機能を正しく果たしているかどうか を検証する •

    実⾏⼿段として、⼿動によるテスト‧⾃動化テス トが存在する • このトークでは、⾃動化テストを取り上げる
  7. © - BASE, Inc. • ৽نςετ࡞੒ίετൃੜ • طଘςετҡ࣋ίετൃੜ • ςετ࣮ߦ࣌ؒͷ଴ͪίετൃੜ

    • ࣗಈςετͷͨΊͷCIҡ࣋ίετൃੜ • Ϣχοτςετͷֶशίετൃੜ ユニットテストの両⾯のコスト Ϣχοτςετ ʹΑΔ ίετ࡟ݮ Ϣχοτςετ ͷ ࡞੒ɾҡ࣋ίετ VS • खಈϢχοτςετͷίετ࡟ݮ • ܽؕͷૣظൃݟʹΑΔमਖ਼ίετ࡟ݮ • υΩϡϝϯςʔγϣϯίετ࡟ݮ • σόοάίετ࡟ݮ • ઃܭվળʹΑΔϝϯςφϯείετ࡟ݮ
  8. © - BASE, Inc. “Communicate Intent”(意図を伝える) • テストをメンテナンスする開発者が、理解しやす くメンテナンスしやすいテストにすること •

    xUTP(※ )の⾃動テストの原則の⼀つ • 理解が難しいコードは、“Obscure Test”と表現 される ※1 ॻ੶ʰxUnit Test Patterns: Refactoring Test Codeʱ / Chapter 5. Principles of Test Automation / ࣗಈςετͷ໨తɾݪଇΛମܥతʹ੔ཧͨ͠ॻ੶
  9. © - BASE, Inc. “Obscure Test”(曖昧なテスト) • ひと⽬で理解することが難しいテスト • ドキュメントとしての効果が減り、メンテナンス

    コストの⾼いテストにつながる Refs ॻ੶ʰxUnit Test Patterns: Refactoring Test Codeʱ / Chapter 15. Code Smells
  10. © - BASE, Inc. • ৽نςετ࡞੒ίετൃੜ • طଘςετҡ࣋ίετൃੜ • ςετ࣮ߦ࣌ؒͷ଴ͪίετൃੜ

    • ࣗಈςετͷͨΊͷCIҡ࣋ίετൃੜ • Ϣχοτςετͷֶशίετൃੜ “Communicate Intent”のメリット Ϣχοτςετ ʹΑΔ ίετ࡟ݮ Ϣχοτςετ ͷ ࡞੒ɾҡ࣋ίετ VS • खಈϢχοτςετͷίετ࡟ݮ • ܽؕͷૣظൃݟʹΑΔमਖ਼ίετ࡟ݮ •υΩϡϝϯςʔγϣϯίετ࡟ݮ • σόοάίετ࡟ݮ • ઃܭվળʹΑΔϝϯςφϯείετ࡟ݮ • 作成者の「意図」が伝わること で、テスト対象コードのドキュメ ンテーションとしての価値が⾼ま る
  11. © - BASE, Inc. • ৽نςετ࡞੒ίετൃੜ •طଘςετҡ࣋ίετൃੜ • ςετ࣮ߦ࣌ؒͷ଴ͪίετൃੜ •

    ࣗಈςετͷͨΊͷCIҡ࣋ίετൃੜ • Ϣχοτςετͷֶशίετൃੜ “Communicate Intent”のメリット Ϣχοτςετ ʹΑΔ ίετ࡟ݮ Ϣχοτςετ ͷ ࡞੒ɾҡ࣋ίετ VS • खಈϢχοτςετͷίετ࡟ݮ • ܽؕͷૣظൃݟʹΑΔमਖ਼ίετ࡟ݮ •υΩϡϝϯςʔγϣϯίετ࡟ݮ • σόοάίετ࡟ݮ • ઃܭվળʹΑΔϝϯςφϯείετ࡟ݮ • テストの可読性が向上すること で、メンテナンス性の良いコード になる。
  12. © - BASE, Inc. “Communicate Intent”の判断 Ϣχοτςετ ʹΑΔ ίετ࡟ݮ Ϣχοτςετ

    ͷ ࡞੒ɾҡ࣋ίετ > • खಈϢχοτςετͷίετ࡟ݮ • ܽؕͷૣظൃݟʹΑΔमਖ਼ίετ࡟ݮ •υΩϡϝϯςʔγϣϯίετ࡟ݮ • σόοάίετ࡟ݮ • ઃܭվળʹΑΔϝϯςφϯείετ࡟ݮ • ৽نςετ࡞੒ίετൃੜ •طଘςετҡ࣋ίετൃੜ • ςετ࣮ߦ࣌ؒͷ଴ͪίετൃੜ • ࣗಈςετͷͨΊͷCIҡ࣋ίετൃੜ • Ϣχοτςετͷֶशίετൃੜ
  13. © - BASE, Inc. +α 失敗の原因を明瞭に伝える適切なエラーレポート • テストコード⾃体が “Communicate Intent”で

    あることが重要 • 発想の⼀つとして、Goのユニットテストについて のアイデアを抑える • テスト結果だけで「なぜ失敗したのか」がわかる “適切なエラーレポート”
  14. © - BASE, Inc. +α Go FAQ: Why does Go

    not have assertions? Go⾔語では、アサートを提供していません。ア サートが便利である点は疑う余地はありませんが、 我々の経験的には、プログラマはアサートを、適切 なエラーハンドリングとエラーレポートを考慮せず に済ますためのツールとして使っています。 (※ 原⽂私訳) Refs: https://golang.org/doc/faq#assertions
  15. © - BASE, Inc. +α Proper error reportingの例 (Go) ===

    RUN TestInStatusList --- FAIL: TestInStatusList ( . s) sample_test.go: : InStatusList(deleted) = false, want true FAIL 直接的かつ適切な内容をレポートに込める ex. “f(x) = y, want z”という⼀つの形式 Refs ॻ੶ʰϓϩάϥϛϯάݴޠGoʱ / ୈ11ষ ςετ
  16. © - BASE, Inc. +α 失敗の原因を明瞭に伝える適切なエラーレポート • ⾔語は違えどエラーレポーティングの考え⽅は頭 の⽚隅に意識しておくとよい •

    PHPUnit\Framework\Assert::assertXxxはメッ セージを渡すことができる • テスト失敗原因が分かりづらいかも知れないと 思ったときに意識すると、メンテナンスコストの 低い費⽤対効果の良いテストコードになりうる
  17. © - BASE, Inc. まとめ: 意図が汲み取りにくいユニットテストがあります 意図が汲み取りにくいユニットテストがあります 問題 障害 戦略

    意図が不明瞭なテストコード “Communicate Intent” 判断 評価 . ドキュメンテーションコス トの削減 . 既存テスト維持コストの削 減 . 該当なし >
  18. © - BASE, Inc. (CM) BASE BANK 銀⾏をかんたんにし、全ての⼈が挑戦できる世の中に MISSION https://thebase.in/yellbank

    • BASE, Inc の100%⼦会社 • 即座に資⾦調達ができる⾦融サービ ス「YELL BANK(エールバンク)」 を運営
  19. © - BASE, Inc. “Keep Tests Independent”(テストを独⽴させる) • テストが相互依存‧順序依存する場合、”独⽴性” がない状態

    • 独⽴していないテストは、 “Erratic Test”(不安 定なテスト)と呼ばれる Refs ॻ੶ʰxUnit Test Patterns: Refactoring Test Codeʱ / Chapter 5. Principles of Test Automation
  20. © - BASE, Inc. “Erratic Test”(不安定なテスト) • “sometimes they pass

    and sometimes they fail” • 不安定な状態を続けると、他の原因での失敗を⾒ 逃してしまうリスクが有る • この問題のトラブルシューティングは難しい Refs ॻ੶ʰxUnit Test Patterns: Refactoring Test Codeʱ / Chapter 15. Code Smells
  21. © - BASE, Inc. 逸脱の常態化(normalization of deviance) “テストスイートへ信頼を失い、「常にこのように 失敗する」と思うようになります。” “間違っているものに慣れすぎて、それを正常で問

    題ないと徐々に受け⼊れ始めることがあるという考 え⽅です。” Refs ॻ੶ʰϚΠΫϩαʔϏεΞʔΩςΫνϟʱ / 7ষ ςετ - 7.6 ৴པͰ͖ͳ͍੬ऑͳςετ
  22. © - BASE, Inc. 不安定なユニットテストがあります 不安定なユニットテストがあります 問題 障害 戦略 実⾏順序で結果が変わるユニットテスト

    “Keep Tests Independent” 判断 評価 . 戦略のメリット . を評価する . 戦略のデメリット . を評価する
  23. © - BASE, Inc. • ৽نςετ࡞੒ίετൃੜ • طଘςετҡ࣋ίετൃੜ • ςετ࣮ߦ࣌ؒͷ଴ͪίετൃੜ

    • ࣗಈςετͷͨΊͷCIҡ࣋ίετൃੜ • Ϣχοτςετͷֶशίετൃੜ “Keep Tests Independent”のメリット Ϣχοτςετ ʹΑΔ ίετ࡟ݮ Ϣχοτςετ ͷ ࡞੒ɾҡ࣋ίετ VS • खಈϢχοτςετͷίετ࡟ݮ •ܽؕͷૣظൃݟʹΑΔ मਖ਼ίετ࡟ݮ • υΩϡϝϯςʔγϣϯίετ࡟ݮ • σόοάίετ࡟ݮ • ઃܭվળʹΑΔϝϯςφϯείετ࡟ݮ • “Erratic Test”(不安定なテス ト)回避効果 • 別の⽋陥‧問題を⾒逃してしまう リストの低下
  24. © - BASE, Inc. • ৽نςετ࡞੒ίετൃੜ •طଘςετҡ࣋ίετൃੜ • ςετ࣮ߦ࣌ؒͷ଴ͪίετൃੜ •

    ࣗಈςετͷͨΊͷCIҡ࣋ίετൃੜ • Ϣχοτςετͷֶशίετൃੜ Ϣχοτςετ ʹΑΔ ίετ࡟ݮ Ϣχοτςετ ͷ ࡞੒ɾҡ࣋ίετ VS • खಈϢχοτςετͷίετ࡟ݮ •ܽؕͷૣظൃݟʹΑΔ मਖ਼ίετ࡟ݮ • υΩϡϝϯςʔγϣϯίετ࡟ݮ • σόοάίετ࡟ݮ • ઃܭվળʹΑΔϝϯςφϯείετ࡟ݮ • “Erratic Test”(不安定なテス ト)回避効果 • トラブルシューティングの難しい コストの掛かる現象の回避 “Keep Tests Independent”メリット
  25. © - BASE, Inc. • ৽نςετ࡞੒ίετൃੜ •طଘςετҡ࣋ίετൃੜ • ςετ࣮ߦ࣌ؒͷ଴ͪίετൃੜ •

    ࣗಈςετͷͨΊͷCIҡ࣋ίετൃੜ •Ϣχοτςετͷ ֶशίετൃੜ “Keep Tests Independent”のデメリット Ϣχοτςετ ʹΑΔ ίετ࡟ݮ Ϣχοτςετ ͷ ࡞੒ɾҡ࣋ίετ VS • खಈϢχοτςετͷίετ࡟ݮ •ܽؕͷૣظൃݟʹΑΔ मਖ਼ίετ࡟ݮ • υΩϡϝϯςʔγϣϯίετ࡟ݮ • σόοάίετ࡟ݮ • ઃܭվળʹΑΔϝϯςφϯείετ࡟ݮ • Super classで共通のtearDown をしていても、個別で必要だった ⽚付けの⾒逃しや⽚付け忘れはあ りうる • その際のErratic Testの原因特定 のために、「何を⽚付けてくれて いるか」知る必要がある • クラスの層ができるので、ある種 の「プロジェクトの仕様」を学習 する機会が発⽣する
  26. © - BASE, Inc. • ৽نςετ࡞੒ίετൃੜ •طଘςετҡ࣋ίετൃੜ • ςετ࣮ߦ࣌ؒͷ଴ͪίετൃੜ •

    ࣗಈςετͷͨΊͷCIҡ࣋ίετൃੜ •Ϣχοτςετͷ ֶशίετൃੜ “Keep Tests Independent”のコスト評価 Ϣχοτςετ ʹΑΔ ίετ࡟ݮ Ϣχοτςετ ͷ ࡞੒ɾҡ࣋ίετ VS • खಈϢχοτςετͷίετ࡟ݮ •ܽؕͷૣظൃݟʹΑΔ मਖ਼ίετ࡟ݮ • υΩϡϝϯςʔγϣϯίετ࡟ݮ • σόοάίετ࡟ݮ • ઃܭվળʹΑΔϝϯςφϯείετ࡟ݮ
  27. © - BASE, Inc. +α テストの実⾏順序を指定する必要がある場合 • TestMethodA -> Bと順序を指定したいケースも

    ありうる • PHPUnitでは、@depends アノテーション等で テストの依存関係を明⽰することも可能 Refs https://phpunit.de/manual/6.5/en/writing-tests-for- phpunit.html#writing-tests-for-phpunit.test-dependencies
  28. © - BASE, Inc. まとめ:不安定なユニットテストがあります > 実⾏順序で結果が変わるユニットテスト 不安定なユニットテストがあります 問題 障害

    戦略 実⾏順序で結果が変わるユニットテスト “Keep Tests Independent” 判断 評価 . ⽋陥の早期発⾒による修コ スト削減 . 既存テスト維持コスト削減 . ユニットテストの学習コス ト発⽣ > <
  29. © - BASE, Inc. “Standard Fixture” • “We reuse the

    design of the test fixture across the many tests. • 複数のテストケースでフィクスチャレコード定義 を共有する戦略 Refs ॻ੶ʰxUnit Test Patterns: Refactoring Test Codeʱ / Chapter 18. Test Strategy Patterns
  30. © - BASE, Inc. “Shared Fixture” “We reuse the design

    of the test fixture across the many tests.
  31. © - BASE, Inc. “Minimal Fixture” • “Use the smallest

    and simplest fixture possible for each test.” • テストケースごとにフィクスチャレコード定義を ⽤意する戦略 Refs ॻ੶ʰxUnit Test Patterns: Refactoring Test Codeʱ / Chapter 18. Test Strategy Patterns
  32. © - BASE, Inc. “Minimal Fixture” “Use the smallest and

    simplest fixture possible for each test.” ex. Larval: Factory, Ruby on Rails: FactoryBot
  33. © - BASE, Inc. 不安定なユニットテストがあります 不安定なユニットテストがあります 問題 障害 戦略 相互依存するデータベースフィクスチャ

    Minimal Fixture / Standard Fixture 判断 評価 . 戦略のメリット . を評価する . 戦略のデメリット . を評価する
  34. © - BASE, Inc. 不安定なユニットテストがあります 不安定なユニットテストがあります 問題 障害 戦略 相互依存するデータベースフィクスチャ

    Minimal Fixture / Standard Fixture 判断 評価 . 戦略のメリット . を評価する . 戦略のデメリット . を評価する Minimal Fixture‧Standard Fixture 2つの戦略の⽐較から考える
  35. © - BASE, Inc. • ৽نςετ࡞੒ίετൃੜ • طଘςετҡ࣋ίετൃੜ • ςετ࣮ߦ࣌ؒͷ଴ͪίετൃੜ

    • ࣗಈςετͷͨΊͷCIҡ࣋ίετൃੜ • Ϣχοτςετͷֶशίετൃੜ “Standard Fixture”のメリット Ϣχοτςετ ʹΑΔ ίετ࡟ݮ Ϣχοτςετ ͷ ࡞੒ɾҡ࣋ίετ VS • खಈϢχοτςετͷίετ࡟ݮ • ܽؕͷૣظൃݟʹΑΔमਖ਼ίετ࡟ݮ • υΩϡϝϯςʔγϣϯίετ࡟ݮ • σόοάίετ࡟ݮ • ઃܭվળʹΑΔϝϯςφϯείετ࡟ݮ • ⼀つの定義で済むのでフィクス チャの作成コストが削減 • ex. ユーザー情報のレコード準備
  36. © - BASE, Inc. • ৽نςετ࡞੒ίετൃੜ • طଘςετҡ࣋ίετൃੜ • ςετ࣮ߦ࣌ؒͷ଴ͪίετൃੜ

    • ࣗಈςετͷͨΊͷCIҡ࣋ίετൃੜ • Ϣχοτςετͷֶशίετൃੜ “Standard Fixture”のデメリット Ϣχοτςετ ʹΑΔ ίετ࡟ݮ Ϣχοτςετ ͷ ࡞੒ɾҡ࣋ίετ VS • खಈϢχοτςετͷίετ࡟ݮ • ܽؕͷૣظൃݟʹΑΔमਖ਼ίετ࡟ݮ • υΩϡϝϯςʔγϣϯίετ࡟ݮ • σόοάίετ࡟ݮ • ઃܭվળʹΑΔϝϯςφϯείετ࡟ݮ • 複数テストケースで共有する分、 相互依存する • テスト間の独⽴性が低下 • 影響範囲を考慮に⼊れたテスト作 成が必要になる
  37. © - BASE, Inc. • ৽نςετ࡞੒ίετൃੜ • طଘςετҡ࣋ίετൃੜ • ςετ࣮ߦ࣌ؒͷ଴ͪίετൃੜ

    • ࣗಈςετͷͨΊͷCIҡ࣋ίετൃੜ • Ϣχοτςετͷֶशίετൃੜ “Standard Fixture”のデメリット Ϣχοτςετ ʹΑΔ ίετ࡟ݮ Ϣχοτςετ ͷ ࡞੒ɾҡ࣋ίετ VS • खಈϢχοτςετͷίετ࡟ݮ • ܽؕͷૣظൃݟʹΑΔमਖ਼ίετ࡟ݮ • υΩϡϝϯςʔγϣϯίετ࡟ݮ • σόοάίετ࡟ݮ • ઃܭվળʹΑΔϝϯςφϯείετ࡟ݮ • フィクスチャレコードが⼤きくな りがちなので、テスト準備に時間 がかかる • テストの実⾏速度が低下する
  38. © - BASE, Inc. • ৽نςετ࡞੒ίετൃੜ • طଘςετҡ࣋ίετൃੜ • ςετ࣮ߦ࣌ؒͷ଴ͪίετൃੜ

    • ࣗಈςετͷͨΊͷCIҡ࣋ίετൃੜ • Ϣχοτςετͷֶशίετൃੜ “Standard Fixture”の評価 Ϣχοτςετ ʹΑΔ ίετ࡟ݮ Ϣχοτςετ ͷ ࡞੒ɾҡ࣋ίετ VS • खಈϢχοτςετͷίετ࡟ݮ • ܽؕͷૣظൃݟʹΑΔमਖ਼ίετ࡟ݮ • υΩϡϝϯςʔγϣϯίετ࡟ݮ • σόοάίετ࡟ݮ • ઃܭվળʹΑΔϝϯςφϯείετ࡟ݮ
  39. © - BASE, Inc. • ৽نςετ࡞੒ίετൃੜ • طଘςετҡ࣋ίετൃੜ • ςετ࣮ߦ࣌ؒͷ଴ͪίετൃੜ

    • ࣗಈςετͷͨΊͷCIҡ࣋ίετൃੜ • Ϣχοτςετͷֶशίετൃੜ “Minimal Fixture”のメリット Ϣχοτςετ ʹΑΔ ίετ࡟ݮ Ϣχοτςετ ͷ ࡞੒ɾҡ࣋ίετ VS • खಈϢχοτςετͷίετ࡟ݮ • ܽؕͷૣظൃݟʹΑΔमਖ਼ίετ࡟ݮ • υΩϡϝϯςʔγϣϯίετ࡟ݮ • σόοάίετ࡟ݮ • ઃܭվળʹΑΔϝϯςφϯείετ࡟ݮ • テストケースごとの影響範囲なの で、最⼩限のフィクスチャレコー ドを⽤意すればいい • エッジケースのテストパターンを 作りやすい • ex. 「利⽤禁⽌ユーザー」
  40. © - BASE, Inc. • ৽نςετ࡞੒ίετൃੜ • طଘςετҡ࣋ίετൃੜ • ςετ࣮ߦ࣌ؒͷ଴ͪίετൃੜ

    • ࣗಈςετͷͨΊͷCIҡ࣋ίετൃੜ • Ϣχοτςετͷֶशίετൃੜ “Minimal Fixture”のメリット Ϣχοτςετ ʹΑΔ ίετ࡟ݮ Ϣχοτςετ ͷ ࡞੒ɾҡ࣋ίετ VS • खಈϢχοτςετͷίετ࡟ݮ • ܽؕͷૣظൃݟʹΑΔमਖ਼ίετ࡟ݮ • υΩϡϝϯςʔγϣϯίετ࡟ݮ • σόοάίετ࡟ݮ • ઃܭվળʹΑΔϝϯςφϯείετ࡟ݮ • 既存テストコードが依存するフィ クスチャの影響範囲が明確 • 影響範囲が理解しやすい分、メン テナンスもしやすいテストフィク スチャになる
  41. © - BASE, Inc. • ৽نςετ࡞੒ίετൃੜ • طଘςετҡ࣋ίετൃੜ • ςετ࣮ߦ࣌ؒͷ଴ͪίετൃੜ

    • ࣗಈςετͷͨΊͷCIҡ࣋ίετൃੜ • Ϣχοτςετͷֶशίετൃੜ “Minimal Fixture”のメリット Ϣχοτςετ ʹΑΔ ίετ࡟ݮ Ϣχοτςετ ͷ ࡞੒ɾҡ࣋ίετ VS • खಈϢχοτςετͷίετ࡟ݮ • ܽؕͷૣظൃݟʹΑΔमਖ਼ίετ࡟ݮ • υΩϡϝϯςʔγϣϯίετ࡟ݮ • σόοάίετ࡟ݮ • ઃܭվળʹΑΔϝϯςφϯείετ࡟ݮ • テストレコードが最⼩限なので、 テスト実⾏速度が(少し)早い
  42. © - BASE, Inc. • ৽نςετ࡞੒ίετൃੜ • طଘςετҡ࣋ίετൃੜ • ςετ࣮ߦ࣌ؒͷ଴ͪίετൃੜ

    • ࣗಈςετͷͨΊͷCIҡ࣋ίετൃੜ • Ϣχοτςετͷֶशίετൃੜ “Minimal Fixture”のデメリット Ϣχοτςετ ʹΑΔ ίετ࡟ݮ Ϣχοτςετ ͷ ࡞੒ɾҡ࣋ίετ VS • खಈϢχοτςετͷίετ࡟ݮ • ܽؕͷૣظൃݟʹΑΔमਖ਼ίετ࡟ݮ • υΩϡϝϯςʔγϣϯίετ࡟ݮ • σόοάίετ࡟ݮ • ઃܭվળʹΑΔϝϯςφϯείετ࡟ݮ • “Standard Fixture”のメリットで もあるテストレコードの再利⽤
  43. © - BASE, Inc. • ৽نςετ࡞੒ίετൃੜ • طଘςετҡ࣋ίετൃੜ • ςετ࣮ߦ࣌ؒͷ଴ͪίετൃੜ

    • ࣗಈςετͷͨΊͷCIҡ࣋ίετൃੜ • Ϣχοτςετͷֶशίετൃੜ “Minimal Fixture”の評価 Ϣχοτςετ ʹΑΔ ίετ࡟ݮ Ϣχοτςετ ͷ ࡞੒ɾҡ࣋ίετ VS • खಈϢχοτςετͷίετ࡟ݮ • ܽؕͷૣظൃݟʹΑΔमਖ਼ίετ࡟ݮ • υΩϡϝϯςʔγϣϯίετ࡟ݮ • σόοάίετ࡟ݮ • ઃܭվળʹΑΔϝϯςφϯείετ࡟ݮ
  44. © - BASE, Inc. まとめ:不安定なユニットテストがあります 不安定なユニットテストがあります 問題 障害 戦略 相互依存するデータベースフィクスチャ

    Minimal Fixture / Standard Fixture 判断 評価 . Minimal Fixtureのメリッ ト/デメリット . Standard Fixtureのメリッ ト/デメリット > <
  45. © - BASE, Inc. ERRORS! Tests: , Assertions: , Errors:

    . ArgumentCountError: Too few arguments to function Hoge::getUserPoint(), passed and exactly expected
  46. © - BASE, Inc. 内部実装に依存したテスト • 内部実装: 公開していない実装情報 • private

    / protected • 内部実装に依存しすぎるテストは、 “Fragile Test” (壊れやすいテスト)と呼ばれる • 振る舞いを変えない改善に対してもテストが反応 してしまう
  47. © - BASE, Inc. “Fragile Test” (壊れやすいテスト) • 修正した箇所と無関係なはずのテストが失敗しは じめる。

    • いくつかの原因のうち、 “Overspecified Software” という状況となっている • テストコードで、テスト対象の振る舞いを過剰 に検証している。 Refs ॻ੶ʰxUnit Test Patterns: Refactoring Test Codeʱ / Chapter 16. Behavior Smells
  48. © - BASE, Inc. “Use the Front Door First”(最初に正⾯⽞関を使う) •

    外部から利⽤することを期待する public インタ フェース と、内部のみからが期待される private インターフェース • テスト対象とは可能な限り、Front Door (public interface)を介した対話をする Refs ॻ੶ʰxUnit Test Patterns: Refactoring Test Codeʱ / Chapter 5. Principles of Test Automation
  49. © - BASE, Inc. 変更頻度が⾼いユニットテストがあります 変更頻度が⾼いユニットテストがあります 問題 障害 戦略 内部実装に依存したテスト

    “Use the Front Door First” 判断 評価 . 戦略のメリット . を評価する . 戦略のデメリット . を評価する
  50. © - BASE, Inc. • ৽نςετ࡞੒ίετൃੜ • طଘςετҡ࣋ίετൃੜ • ςετ࣮ߦ࣌ؒͷ଴ͪίετൃੜ

    • ࣗಈςετͷͨΊͷCIҡ࣋ίετൃੜ • Ϣχοτςετͷֶशίετൃੜ “Use the Front Door First”のメリット Ϣχοτςετ ʹΑΔ ίετ࡟ݮ Ϣχοτςετ ͷ ࡞੒ɾҡ࣋ίετ VS • खಈϢχοτςετͷίετ࡟ݮ • ܽؕͷૣظൃݟʹΑΔमਖ਼ίετ࡟ݮ • υΩϡϝϯςʔγϣϯίετ࡟ݮ • σόοάίετ࡟ݮ • ઃܭվળʹΑΔ ϝϯςφϯείετ࡟ݮ • クラスの責務の⾒直しによる設計 改善 • メンテナンス性の⾼い動作コード へ
  51. © - BASE, Inc. • ৽نςετ࡞੒ίετൃੜ • طଘςετҡ࣋ίετൃੜ • ςετ࣮ߦ࣌ؒͷ଴ͪίετൃੜ

    • ࣗಈςετͷͨΊͷCIҡ࣋ίετൃੜ • Ϣχοτςετͷֶशίετൃੜ “Use the Front Door First”のメリット Ϣχοτςετ ʹΑΔ ίετ࡟ݮ Ϣχοτςετ ͷ ࡞੒ɾҡ࣋ίετ VS • खಈϢχοτςετͷίετ࡟ݮ • ܽؕͷૣظൃݟʹΑΔमਖ਼ίετ࡟ݮ • υΩϡϝϯςʔγϣϯίετ࡟ݮ • σόοάίετ࡟ݮ • ઃܭվળʹΑΔ ϝϯςφϯείετ࡟ݮ • 動作コードの変更に対する変更頻度の減少
  52. © - BASE, Inc. • ৽نςετ࡞੒ίετൃੜ • طଘςετҡ࣋ίετൃੜ • ςετ࣮ߦ࣌ؒͷ଴ͪίετൃੜ

    • ࣗಈςετͷͨΊͷCIҡ࣋ίετൃੜ • Ϣχοτςετͷֶशίετൃੜ “Use the Front Door First”のデメリット Ϣχοτςετ ʹΑΔ ίετ࡟ݮ Ϣχοτςετ ͷ ࡞੒ɾҡ࣋ίετ VS • खಈϢχοτςετͷίετ࡟ݮ • ܽؕͷૣظൃݟʹΑΔमਖ਼ίετ࡟ݮ • υΩϡϝϯςʔγϣϯίετ࡟ݮ • σόοάίετ࡟ݮ • ઃܭվળʹΑΔ ϝϯςφϯείετ࡟ݮ • テスト対象の内部処理は “ブラックボックス” として扱 いテストしすぎない • (外側から⾒た振る舞いを検証する) • 内部の private に複雑なロジックが詰め込まれている 場合、振る舞い保証が不⼗分な可能性も。
  53. © - BASE, Inc. • ৽نςετ࡞੒ίετൃੜ • طଘςετҡ࣋ίετൃੜ • ςετ࣮ߦ࣌ؒͷ଴ͪίετൃੜ

    • ࣗಈςετͷͨΊͷCIҡ࣋ίετൃੜ • Ϣχοτςετͷֶशίετൃੜ “Use the Front Door First”の評価 Ϣχοτςετ ʹΑΔ ίετ࡟ݮ Ϣχοτςετ ͷ ࡞੒ɾҡ࣋ίετ VS • खಈϢχοτςετͷίετ࡟ݮ • ܽؕͷૣظൃݟʹΑΔमਖ਼ίετ࡟ݮ • υΩϡϝϯςʔγϣϯίετ࡟ݮ • σόοάίετ࡟ݮ • ઃܭվળʹΑΔ ϝϯςφϯείετ࡟ݮ
  54. © - BASE, Inc. まとめ:変更頻度が⾼いユニットテストがあります 変更頻度が⾼いユニットテストがあります 問題 障害 戦略 内部実装に依存したテスト

    “Use the Front Door First” 判断 評価 . 設計改善によるメンテナン スコスト削減 . 既存テスト維持コスト . ⽋陥の早期発⾒による修正 コスト増加(の可能性) > <
  55. © - BASE, Inc. ERRORS! Tests: , Assertions: , Errors:

    . Expectation failed for method name is equal to <string:getByCustomerId> when invoked time(s). Method was expected to be called times, actually called times.
  56. © - BASE, Inc. “Mock” を定義するためのxUTPによる語彙整理 Test Double: テスト固有の同等物 Mock:

    テスト対象に適切に使⽤されているか検証 する Refs ॻ੶ʰxUnit Test Patterns: Refactoring Test Codeʱ / Chapter 23. Test Double Patterns
  57. © - BASE, Inc. このトーク内での “Mock” は「広義のMock Object」 Refs ॻ੶ʰςετۦಈ։ൃʱ

    / ෇࿥C Ϣχοτςετपลͷ஌ࣝͷ੔ཧͱTDD֦ுͷࢼΈ • xUTPの語彙整理により、「広義のMock Object」‧「狭義のMock Object」を分けて議 論できるようになった • このトークでの “Mock” もTest Doubleの範囲を ざっくりと含める「広義のMock Object」とする
  58. © - BASE, Inc. 的確なエクスペクテーション Refs ॻ੶ʰ࣮ફςετۦಈ։ൃʱ / ୈ20ষ ςετͷ੠Λௌ͘

    “意図を明確にするためには、スタブとエクスペク テーション‧アサーションをきっちり区別するとよ い。”
  59. © - BASE, Inc. 区別するための指標:コマンド/クエリ Refs ॻ੶ʰ࣮ફςετۦಈ։ൃʱ / ୈ20ষ ςετͷ੠Λௌ͘

    ΫΤϦʹ͸ΞϩʔΞϯεɺίϚϯυʹ͸ΤΫεϖΫςʔγϣϯ • コマンドとは、 副作⽤を伴うことのある呼び出し • オブジェクトの外の世界を変化させる • ex. DBのレコード保存‧状態変化 • 複数回実⾏した場合、システム状態は違ったもの になる => エクスペクテーション
  60. © - BASE, Inc. 区別するための指標:コマンド/クエリ • クエリは、外の世界を変化させない • 何回呼んでも呼ばなくても構わない •

    ⇒ アローアンス Refs ॻ੶ʰ࣮ફςετۦಈ։ൃʱ / ୈ20ষ ςετͷ੠Λௌ͘ ΫΤϦʹ͸ΞϩʔΞϯεɺίϚϯυʹ͸ΤΫεϖΫςʔγϣϯ
  61. © - BASE, Inc. 変更頻度が⾼いユニットテストがあります
 > Mockが妨げるユニットテスト 変更頻度が⾼いユニットテストがあります 問題 障害

    戦略 Mockが妨げるユニットテスト “的確なエクスペクテーション” 判断 評価 . 戦略のメリット . を評価する . 戦略のデメリット . を評価する
  62. © - BASE, Inc. • ৽نςετ࡞੒ίετൃੜ • طଘςετҡ࣋ίετൃੜ • ςετ࣮ߦ࣌ؒͷ଴ͪίετൃੜ

    • ࣗಈςετͷͨΊͷCIҡ࣋ίετൃੜ • Ϣχοτςετͷֶशίετൃੜ “的確なエクスペクテーション”のメリット Ϣχοτςετ ʹΑΔ ίετ࡟ݮ Ϣχοτςετ ͷ ࡞੒ɾҡ࣋ίετ VS • खಈϢχοτςετͷίετ࡟ݮ • ܽؕͷૣظൃݟʹΑΔमਖ਼ίετ࡟ݮ • υΩϡϝϯςʔγϣϯίετ࡟ݮ • σόοάίετ࡟ݮ • ઃܭվળʹΑΔϝϯςφϯείετ࡟ݮ • テストコードのモックオブジェク トが適切にコントロールされる • 対象オブジェクトが他オブジェク トとどう協調するかがテストに よって⽰される
  63. © - BASE, Inc. • ৽نςετ࡞੒ίετൃੜ • طଘςετҡ࣋ίετൃੜ • ςετ࣮ߦ࣌ؒͷ଴ͪίετൃੜ

    • ࣗಈςετͷͨΊͷCIҡ࣋ίετൃੜ • Ϣχοτςετͷֶशίετൃੜ “的確なエクスペクテーション”のメリット Ϣχοτςετ ʹΑΔ ίετ࡟ݮ Ϣχοτςετ ͷ ࡞੒ɾҡ࣋ίετ VS • खಈϢχοτςετͷίετ࡟ݮ • ܽؕͷૣظൃݟʹΑΔमਖ਼ίετ࡟ݮ • υΩϡϝϯςʔγϣϯίετ࡟ݮ • σόοάίετ࡟ݮ • ઃܭվળʹΑΔϝϯςφϯείετ࡟ݮ • 動作コードの変更に対する変更頻度の減少
  64. © - BASE, Inc. • ৽نςετ࡞੒ίετൃੜ • طଘςετҡ࣋ίετൃੜ • ςετ࣮ߦ࣌ؒͷ଴ͪίετൃੜ

    • ࣗಈςετͷͨΊͷCIҡ࣋ίετൃੜ • Ϣχοτςετͷֶशίετൃੜ “的確なエクスペクテーション”のデメリット Ϣχοτςετ ʹΑΔ ίετ࡟ݮ Ϣχοτςετ ͷ ࡞੒ɾҡ࣋ίετ VS • खಈϢχοτςετͷίετ࡟ݮ • ܽؕͷૣظൃݟʹΑΔ मਖ਼ίετ࡟ݮ • υΩϡϝϯςʔγϣϯίετ࡟ݮ • σόοάίετ࡟ݮ • ઃܭվળʹΑΔϝϯςφϯείετ࡟ݮ • すべてエクスペクテーションにすると、過剰では あるがテスト対象オブジェクトの内部処理が”よ り”テストされる。
  65. © - BASE, Inc. • ৽نςετ࡞੒ίετൃੜ • طଘςετҡ࣋ίετൃੜ • ςετ࣮ߦ࣌ؒͷ଴ͪίετൃੜ

    • ࣗಈςετͷͨΊͷCIҡ࣋ίετൃੜ • Ϣχοτςετͷֶशίετൃੜ “的確なエクスペクテーション”の評価 Ϣχοτςετ ʹΑΔ ίετ࡟ݮ Ϣχοτςετ ͷ ࡞੒ɾҡ࣋ίετ VS • खಈϢχοτςετͷίετ࡟ݮ • ܽؕͷૣظൃݟʹΑΔ मਖ਼ίετ࡟ݮ • υΩϡϝϯςʔγϣϯίετ࡟ݮ • σόοάίετ࡟ݮ • ઃܭվળʹΑΔϝϯςφϯείετ࡟ݮ
  66. © - BASE, Inc. まとめ:変更頻度が⾼いユニットテストがあります
 > Mockが妨げるユニットテスト 変更頻度が⾼いユニットテストがあります 問題 障害

    戦略 Mockが妨げるユニットテスト “的確なエクスペクテーション” 判断 評価 . ドキュメンテーションコス ト削減 . 既存テスト維持コスト削減 . ⽋陥の早期発⾒による修正 コスト削減 > <
  67. © - BASE, Inc. 参考‧引⽤資料 - トーク内で引⽤した書籍 • 『xUnit Test

    Patterns: Refactoring Test Code』 • 『テスト駆動開発』 • 『実践テスト駆動開発』 • 『マイクロサービスアーキテクチャ』 • 『レガシーコード改善ガイド』 • 『プログラミング⾔語Go』
  68. © - BASE, Inc. 参考‧引⽤資料 - トーク構築に寄与した書籍 • 『オブジェクト指向設計実践ガイド ~Rubyでわかる

    進化しつづける柔軟 なアプリケーションの育て⽅』 • 『ソフトウェア‧テストの技法 第2版』 • 『プログラマが知るべき97のこと』 • 『リファクタリング 既存のコードを安全に改善する』 • 『Clean Code アジャイルソフトウェア達⼈の技』 • 『初めての⾃動テスト』 • 『Succeeding with Agile: Software Development Using Scrum』 • 『エキスパートPythonプログラミング 改訂2版』