Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

xUnit Test Patterns - Chapter16

3,353 views

Published on

handout for xUnit Test Patterns Reading Group Japan

Published in: Technology
  • Be the first to comment

xUnit Test Patterns - Chapter16

  1. 1. Chapter 16. Behavior Smells
  2. 2. Smells in This Chapter ● Assertion Roulette ● Erratic Test ● Fragile Test ● Frequent Debugging ● Manual Intervention ● Slow Tests
  3. 3. Assertion Roulette
  4. 4. Assertion Roulette (1) ● 初出 ● XP2001 “Refactoring Test Code” ● Symptoms ● テスト失敗時に、どの assertion が失敗したのかよ く分からない ● Impact ● CI 中にテストが Assertion Roulette が発現した場 合には解析が難しい。手元のマシンで再現できない 時はさらに時間を食うことになる
  5. 5. Assertion Roulette (2) ● Causes ● Eager Test – ひとつのテストで機能を検証しすぎている ● Missing Assertion Message – アサーションメッセージが無い
  6. 6. Smells in This Chapter ● Assertion Roulette ● Eager Test ● Missing Assertion Message ● Erratic Test ● Fragile Test ● Frequent Debugging ● Manual Intervention ● Slow Tests
  7. 7. Eager Test (1) ● Symptoms ● ひとつのテストが SUT の複数のメソッドをテスト している ● ひとつのテストが SUT の同じメソッドを fixture setup logic や assertion などバラバラな場所から 複数回呼んでいる ● テスト技術者がテストフレームワークを改造して assertion が失敗してもその行以降を実行させよう とする
  8. 8. public void testFlightMileage_asKm2() throws Exception { //set up fixture //exercise constructor Flight newFlight = new Flight(validFlightNumber); //verify constructed object assertEquals(validFlightNumber, newFlight.number); assertEquals("", newFlight.airlineCode); assertNull(newFlight.airline); //set up mileage     newFlight.setMileage(1122); //exercise mileage translator int actualKilometres = newFlight.getMileageAsKm(); //verify results int expectedKilometres = 1810; assertEquals( expectedKilometres, actualKilometres); //now try it with a canceled flight newFlight.cancel(); try { newFlight.getMileageAsKm(); fail("Expected exception"); } catch (InvalidRequestException e) { assertEquals( "Cannot get cancelled flight mileage", e.getMessage()); } }
  9. 9. Eager Test (2) ● Root Cause ● テストの中で多くの検証を行って (意図的であるに しろ無いにしろ) テストの数を最小にしようとする こと – 手動テストにおいては一度にたくさんの要素をテストす るのは良いこととされているが、完全自動化されたテス トにおいては悪手 ● 多くのステップを必要とする Customer Test を xUnit を使って行おうとすること
  10. 10. Eager Test (3) ● Possible Solution ● Single-Condition Test (p45) に分解する – Extract Method [Fowler] – ひとつひとつのテスト要素毎にコピーして不要な部分を 削除 ● Creation Method (p415) – Fixture を setup したり SUT を特定の状態にする部分 をメソッドに切り出す – Lean on Compiler [WEwLC] 使おう
  11. 11. Eager Test (4) ● Customer Test を xUnit で行っている場合 – テストシナリオが進むに応じて複雑な状態がテスト内で 作り出されていく – テスト後半部分を切り出すためには複雑な状態の setup が必要なので、なんらかの手段を講じる必要がある ● Back Door Setup (p327) を使ってテスト後半部分 の setup を行えればテストを分割できる – Defect Localization につながる – テストを短くしていけば Communicate Intent (p41) へ
  12. 12. Smells in This Chapter ● Assertion Roulette ● Eager Test ● Missing Assertion Message ● Erratic Test ● Fragile Test ● Frequent Debugging ● Manual Intervention ● Slow Tests
  13. 13. Missing Assertion Message (1) ● Symptoms ● テスト失敗時に、どの assertion が失敗したのか よく分からない
  14. 14. Missing Assertion Message (2) ● Root Cause ● Assertion Method (p362) が – 同じ Assertion Method が複数回使われている – Assertion Message (p370) 無しで書かれている ● コマンドラインからテストを実行したり、開発環境 とテストコードが統合されていない時にどこで失敗 したか分からず困る
  15. 15. public void testInvoice_addLineItem7() { LineItem expItem = new LineItem(inv, product, QUANTITY); //Exercise inv.addItemQuantity(product, QUANTITY); //Verify List lineItems = inv.getLineItems(); LineItem actual = (LineItem)lineItems.get(0); assertEquals(expItem.getInv(), actual.getInv());     assertEquals(expItem.getProd(), actual.getProd()); assertEquals(expItem.getQuantity(), actual.getQuantity()); } 失敗した時に見分けはつくか? Meszaros says: 同じタイプの Assertion Method を使うときは Assertion Message を書いておくこと t-wada says: Assertion Message も Smell では?
  16. 16. Missing Assertion Message (3) ● Possible Solution ● GUI のある IDE の場合はスタックトレースをクリックして 飛んで、ブレークポイントつけて再実行できたりする ● コマンドラインで実行している場合には GUI ランナーや IDE で実行して落ちている assertion を見つけよう ● それらもダメな場合は行番号を追ったり、もっと深追いし なければならない ● そんな頑張らずに、数字でもいいから Assertion Message 入れよう (そういえばひがさんはそうしてた)
  17. 17. Smells in This Chapter ● Assertion Roulette ● Erratic Test ● Fragile Test ● Frequent Debugging ● Manual Intervention ● Slow Tests
  18. 18. Erratic Test
  19. 19. erratic 【名】 1. 変人、奇人 2. 《地学》迷子石◆【同】erratic boulder 【形】 1. 〔人の言動が〕とっぴな、風変わりな、異常な、常軌を逸した 2. 一貫性のない、不安定な、一定しない、出来不出来がある、不 規則な 3. 《地学》〔石などが氷河で〕漂移した
  20. 20. Erratic Test (1) ● 成功したり失敗したり、動きが一定でない ● Symptoms ● いつ実行したかや誰が実行したかによってテストの 結果が異なる ● 同じ Test Runner で実行しても結果がバラバラな ことがある
  21. 21. Erratic Test (2) ● Impact ● いつも Test Suite を緑にしたいので Erratic Test を suite から外し、Lost Test (p268) につながる ● Suite に入れたままにしたらしたで、他のテストで 赤が出たときに気づかなかったりする
  22. 22. Erratic Test (3) ● Troubleshooting Advice ● 原因がいろいろあるので手強い ● 簡単に見つからない場合にはデータを定期的に採っ て調べる必要がある – どこで成功し、どこで失敗したか – 全部のテストを実行したのか、一部を実行したのか – 同じ行を何度も実行した時に振る舞いが変わったか – 複数の Test Runner を同時に実行した時に振る舞いが 変わったか
  23. 23. Erratic Test (4) ● Troubleshooting Advice ● 原因がいろいろあるので手強い ● 簡単に見つからない場合にはデータを定期的に採っ て調べる必要がある – どこで成功し、どこで失敗したか – 全部のテストを実行したのか、一部を実行したのか – 同じ行を何度も実行した時に振る舞いが変わったか – 複数の Test Runner を同時に実行した時に振る舞いが 変わったか ● データが採れたら次のページの切り分け図へ
  24. 24. Erratic Test (5)
  25. 25. Erratic Test Causes ● Assertion Roulette ● Erratic Test ● Interacting Tests ● Interacting Test Suites ● Lonely Test ● Resource Leakage ● Resource Optimism ● Unrepeatable Test ● Test Run War ● Nondeterministic Test ● Fragile Test ● Frequent Debugging ● Manual Intervention ● Slow Tests
  26. 26. Erratic Test Causes ● Erratic Test ● Interacting Tests ● Interacting Test Suites ● Lonely Test ● Resource Leakage ● Resource Optimism ● Unrepeatable Test ● Test Run War ● Nondeterministic Test
  27. 27. Interacting Tests (1) ● テストが他のテストに何らかの形で依存してい る ● バリエーション ● Interacting Test Suite ● Lonely Test
  28. 28. Interacting Tests (2) ● Symptoms ● 独立して動かすときには成功しているテストが以下 の状況下で失敗する – 他のテストが suite に追加 / 削除されたとき – Suite の他のテストが失敗 / 成功したとき – テスト自身、もしくは他のテストのファイル名が変更さ れたとき – Test Runner の新バージョンがインストールされたとき
  29. 29. Interacting Tests (3) ● Root Cause ● 多くの場合、 Shared Fixture (p317) を使ってい てかつ他のテストの (Shared Fixture への) 出力に 依存しているために発生する ● 二つの側面から説明できる – The mechanism of interaction – The reason of interaction
  30. 30. Interacting Tests (4) ● The Mechanism of interaction ● テスト (インスタンス) の寿命より長いものを使う ときに起こる – データベース – static 変数 ● やめておいたほうがいいもの – Singleton [GoF] – Registry [PofEAA]
  31. 31. Interacting Tests (5) ● The Reason of interaction ● 他のテストの fixture setup phase で作られる fixture に依存している ● 他のテストが SUT に与える変化に依存している ● 相互排他に行うべきテストを同時に行うことによる 競合
  32. 32. Interacting Tests (5) ● 依存関係が終わるとき ● 依存している他のテストが – suite からいなくなる – SUT を変化させなくなる – SUT を変化させる際に失敗するようになる – 改名などにより、テスト実行の順番が後ろになる ● 競合が始まるとき ● 競合しているテストが – suite に加わる – 初めて成功した時点 – テスト実行の順番が前になったとき
  33. 33. Interacting Tests (6) ● テスト対象自体は正しいのに失敗するようにな るので、 “false-positive” になる。 ● 一般論としてテスト実行順に依存するのは良く ない ● xUnit ファミリーは実行順を保証しない ● TestNG は保証する
  34. 34. Interacting Tests (7) ● Possible Solution ● Fresh Fixture (p311) – もっとも望ましい ● Shared Fixture を使いたい場合は – Immutable Shared Fixture ● 他のテストが作成するオブジェクトに依存している 時は – 両方のテストに Lazy Setup (p435) を書く ● コードが重複する場合は – Creation Method (p415) – Test Helper (p643)
  35. 35. Interacting Tests (8) ● Possible Solution (Cont'd) ● テストで作成されたものが残っていることによる競 合には – Automated Fixture Teardown (p503) ● テストの依存を見つける方法 ● いつもと違う順番で実行してみる – すべてのテストを逆順に実行してみる ● 普段から常にバラバラの順番でテストを実行するよ うにしておくと事故を防げて良い
  36. 36. Erratic Test Causes ● Erratic Test ● Interacting Tests ● Interacting Test Suites ● Lonely Test ● Resource Leakage ● Resource Optimism ● Unrepeatable Test ● Test Run War ● Nondeterministic Test
  37. 37. Interacting Test Suites (1) ● Symptoms ● Suite 単体では成功するが、 Suite の Suite とい う構成にすると失敗する ● Root Cause ● よくあるのは、同じリソースを Suite が作成しよ うとし、後から実行された Suite のほうが失敗す るケース
  38. 38. Interacting Test Suites (2) ● 探すには ● 失敗したテストを見る ● それでも分からない時には – 成功している方の Suite からテストを一つずつ取り除く ● 失敗しなくなったときに取り除いたテストが依存元 ● 場所はどこか – Shared Fixture – Test Method 内 – Setup method – Test Utility
  39. 39. Interacting Test Suites (3) ● Root Cause (Cont'd) ● 依存しあっているのは一つのテストとは限らない ● テストケースではなく Suite Fixture Setup や Setup Decorator が引き金となっているかもしれ ない ● NUnit についてまたいろいろ書いているが割愛
  40. 40. Interacting Test Suites (4) ● Possible Solution ● 一番いいのは全部 Fresh Fixture にすること ● Fresh Fixture にするのが難しければ Immutable Shared Fixture ● データベースに残っている残骸が問題なら Automated Teardown
  41. 41. Erratic Test Causes ● Erratic Test ● Interacting Tests ● Interacting Test Suites ● Lonely Test ● Resource Leakage ● Resource Optimism ● Unrepeatable Test ● Test Run War ● Nondeterministic Test
  42. 42. Lonely Test (1) ● Interacting Tests の特殊例 ● Suite の一部としては実行成功するが、単独で は動かない ● 他のテストの触った Shared Fixture に依存してい る – Chained Tests – Suite-level fixture setup
  43. 43. Erratic Test Causes ● Erratic Test ● Interacting Tests ● Interacting Test Suites ● Lonely Test ● Resource Leakage ● Resource Optimism ● Unrepeatable Test ● Test Run War ● Nondeterministic Test
  44. 44. Resource Leakage (1) ● Symptoms ● テストがだんだん遅くなり、ついには失敗しだすように なる ● Test Runner / SUT / Database Sandbox(p650) をク リーンアップするとテストが通るようになる ● Root Cause ● 有限リソースをテストが消費し、それの開放に失敗して いる ● テストがどんどん遅くなる ● テストを連続して続けるとリソースが使い尽くされ、後 続のテストが失敗し始める
  45. 45. Resource Leakage (2) ● Root Cause (Cont'd) ● SUT がリソースの開放に失敗している – これが判明したら、直すのも難しくない ● テストが fixture setup でリソースを消費し、開 放に失敗している
  46. 46. Resource Leakage (3) ● Possible Solution ● SUT がリソースを開放していないとき – テストは仕事をきちんとしているので SUT のバグを直 すべし ● テスト失敗時にリソース開放に失敗している場合 – Guaranteed In-line Teardown (p509) – Automated Teardown ● リソースプールのサイズを 1 にするのがいい ● 問題がある場合にはテストがすぐ失敗するようにな り、気づきやすい
  47. 47. Erratic Test Causes ● Erratic Test ● Interacting Tests ● Interacting Test Suites ● Lonely Test ● Resource Leakage ● Resource Optimism ● Unrepeatable Test ● Test Run War ● Nondeterministic Test
  48. 48. Resource Optimism ● Symptoms ● ある環境下で動くテストが他の環境下で失敗する ● Root Cause ● ある環境に存在するリソースが他の環境で不在 ● Possible Solution ● 可能なら、 Fresh Fixture をテストから毎回作成す るようにする – 相対パスを使ってファイルを生成するなど ● 外部リソースを使わなければならない場合には SCM に入れることも視野に入れる
  49. 49. Erratic Test Causes ● Erratic Test ● Interacting Tests ● Interacting Test Suites ● Lonely Test ● Resource Leakage ● Resource Optimism ● Unrepeatable Test ● Test Run War ● Nondeterministic Test
  50. 50. Unrepeatable Test (1) ● Symptoms ● あるテストがテスト群の先頭にある場合はテストが 成功し、後続にある場合は失敗する。もしくはその 逆。 – Pass-Fail-Fail – Fail-Pass-Pass
  51. 51. Unrepeatable Test (2) ● Root Cause ● (意図の有無に関わらず) Shared Fixture の使用 – Prebuilt Fixture を使っている場合にはDatabase ● Sandbox を使っていても、同一の開発者が同一の テストランナーを使ったときは発生する ● Lazy Setup を使っている場合には、 fixture が class 変数を使いつづけたりする
  52. 52. Unrepeatable Test (3) ● Possible Solution ● Fresh Fixture! – Database Sandbox すら生ぬるい ● Fake Database (p551) ● 共有 Database を使わなければならない場合には Distinct Generated Values (p723) ● Automated Teardown
  53. 53. Erratic Test Causes ● Erratic Test ● Interacting Tests ● Interacting Test Suites ● Lonely Test ● Resource Leakage ● Resource Optimism ● Unrepeatable Test ● Test Run War ● Nondeterministic Test
  54. 54. Test Run War (1) ● Symptoms ● 一人でテストを実行する時はテストが成功するが、 複数人が同時にテストを実行すると失敗する ● Impact ● カットオフ間近に発生しがちだからイライラする! ● 「テストが落ちたら最後の変更を疑え」ルールが機 能しなくなる
  55. 55. Test Run War (2) ● Root Cause ● Shared Fixture (Database) – 行の UPDATE / DELETE / SELECT などの競合 – 悲観ロック ● Shared Fixture (File) – 既に他の人がファイルを開いているなど
  56. 56. Test Run War (3) ● Possible Solution ● Fresh Fixture (★何回目?) ● Test Runner 毎に Database Sandbox を使う – しかしこれではまだ Shared Fixture 経由の Interacting Test は解決しない ● Immutable Shared Fixture – Test の変更が若干必要かも ● データベースに残る残骸が問題なら Automated Teardown – Test Run War の根本解決にはならないが、確率が減る
  57. 57. Erratic Test Causes ● Erratic Test ● Interacting Tests ● Interacting Test Suites ● Lonely Test ● Resource Leakage ● Resource Optimism ● Unrepeatable Test ● Test Run War ● Nondeterministic Test
  58. 58. Nondeterministic Test (1) ● Symptoms ● テストがランダムに失敗する – 人や環境、同時実行にも関係なさそう ● 複数の Nondeterministic Test が suite にあると 問題判別が難しい ● Impact ● デバッグに時間がかかりすぎるし、イライラする
  59. 59. Nondeterministic Test (2) ● Root Cause ● テスト毎に異なる値を使うことによって発生する – ただし、異なる値を使うこと自体は悪いことではない。 (例 : Distinct Generated Value) – テスト対象アルゴリズムへの入力にランダムな値を使う ときに問題が発生する ● Integer の負数や臨界値など ● 長さ限界の文字列など ● ランダム値を使うことは悪くないように思えるが、 カバレッジへの信頼とテストの repeatabilty が下 がる
  60. 60. Nondeterministic Test (3) ● Root Cause (Cont'd) ● Conditional Test Logic の使用がテストにランダ ムさをもたらす – テスト毎にテスト実行パスが異なる
  61. 61. Nondeterministic Test (4) ● Possible Solution ● Conditional Test Logic を取り除いて Linear に実 行されるようにする ● ランダム値の使用を止めて deterministic な値を 使うようにする ● 臨界値や同値分割を使う ● テストが重複し始めたら – Parameterized Test (p607) – Data-Driven Test (p288)
  62. 62. Smells in This Chapter ● Assertion Roulette ● Erratic Test ● Fragile Test ● Frequent Debugging ● Manual Intervention ● Slow Tests
  63. 63. Fragile Test
  64. 64. fragile 【形】 1. 壊れやすい、もろい、割れやすい、脆弱な、傷 (が)付きやすい、駄目になりやすい、危うい、軽 い、か弱い、はかない、きゃしゃな 2. 実質のない、不十分な 3. 束の間の、逼迫した 4. 虚弱な、元気がない、調子が悪い
  65. 65. Fragile Test (1) ● Symptoms ● 全然関係ないと思っていた部分の修正で、テストが コンパイル/実行に失敗し始める – ときには production code に手を触れていないのに失敗 し始めることも ● テスト自動化に頑張っていればいるほど、”four sensitivities” (4 つの過敏症) に引っかかりやすく なる
  66. 66. Fragile Test (2) ● Impact ● 変更を行う際にあちこちのテストを見なければなら ないため、テストのメンテナンスコストが上がる ● Incremental delivery を行う XP のようなプロセ スでは、テストのメンテナンスコスト増は致命傷に なりうる
  67. 67. Fragile Test (3) ● Troubleshooting Advice ● 「落ちたテストに共通点は無いか?」と自問しよう – テストと SUT の結合点が見えてくる ● 4 sensitivities ● Interface Sensitivity – コンパイルに失敗する – 動的型付け言語では型非互換ランタイムエラー ● Behavior Sensitivity – 直前の変更を戻したらテストが通るようになる
  68. 68. Fragile Test (4) ● Troubleshooting Advice (Cont'd) ● Data Sensitivity – 直前のコード変更を戻してもテストが失敗する ● Shared Fixture を使っている or Fixture setup code を変更し た ● Context Sensitivity – 直前のコード変更を戻してもテストが失敗する ● テストコードもテストデータもいじってない
  69. 69. Fragile Test (5) ● Troubleshooting Advice (Cont'd) ● Data Sensitivity – 直前のコード変更を戻してもテストが失敗する ● Shared Fixture を使っている or Fixture setup code を変更し た ● Context Sensitivity – 直前のコード変更を戻してもテストが失敗する ● テストコードもテストデータもいじってない
  70. 70. Fragile Test (6)
  71. 71. Fragile Test (7) ● Causes ● Indirect Testing – SUT に他のオブジェクトを介してアクセスしている ● Eager Tests – テストで検証をしすぎている ● SUT の結合度が強すぎることの現れ – そもそも小さい単位でテストするのが難しい SUT なの かもしれない (Hard-to-Test Code) – Test Doubles を使い慣れていないだけかもしれない
  72. 72. Fragile Test Causes ● Fragile Test ● Interface Sensitivity ● Behavior Sensitivity ● Data Sensitivity ● Context Sensitivity ● Overspecified Software ● Sensitive Equality ● Fragile Fixture
  73. 73. Interface Sensitivity ● Symptoms ● SUT が変更されるとテストのコンパイル/実行に失 敗する – 静的型付け言語の場合はテストコンパイル失敗 – 動的型付け言語の場合はテスト実行失敗 – (変種) GUI 経由で Recorded Test を行っている場合 は、 UI 変更でテスト実行に失敗するとか
  74. 74. Interface Sensitivity (2) ● Possible Solution ● 原因はわかりやすいことが多い – コンパイル/テスト失敗する場所が問題箇所 – 結局変更点が引き金になっていることが多い ● 内部で使われる interface の場合には SUT API Encapsulation – テスト用の Higher-Level Language (p41) を組む ● Test Utility Methods ● Creation Methods ● “公布済み interface” の場合にはきちんと管理する しかない
  75. 75. Fragile Test Causes ● Fragile Test ● Interface Sensitivity ● Behavior Sensitivity ● Data Sensitivity ● Context Sensitivity ● Overspecified Software ● Sensitive Equality ● Fragile Fixture
  76. 76. Behavior Sensitivity ● Symptoms ● SUT が変更されると関係ない部分のテストの実行に失 敗する ● Root Cause ● テストが失敗する事自体は悪くない。自動テストはそ のためにある。 ● Behavior Sensitivity になるのは、関係ないと思って いたテストの以下の部分が失敗するとき – Pre-test state setup (fixture setup) – Post-test state verification – Tear down (fixture teardown)
  77. 77. Behavior Sensitivity (2) ● Possible Solution ● Fixture setup に失敗しているとき – Creation Method ● State Verification に失敗しているとき – Custom Assertion – Verification Method ● (fixture teardown が無いが…たぶん) – Test Utility Method – Delegated Teardown
  78. 78. Fragile Test Causes ● Fragile Test ● Interface Sensitivity ● Behavior Sensitivity ● Data Sensitivity ● Context Sensitivity ● Overspecified Software ● Sensitive Equality ● Fragile Fixture
  79. 79. Data Sensitivity ● Symptoms ● テストデータが変更されるとテストの実行に失敗す る – 既存テストデータの追加、更新、削除 – Standard Fixture のセットアップコードが変更された – テスト実行前に Shared Fixture が変更されている ● Root Cause ● データが変わっている! – 検索に余計に引っかかるとか – 無くなっているとか
  80. 80. Data Sensitivity (2) ● Possible Solution ● 多くの場合 result verification で発生する – Verification logic を見直す ● 一番良いのは Fresh Fixture ● Database Partitioning Scheme ● Delta Assertions
  81. 81. Fragile Test Causes ● Fragile Test ● Interface Sensitivity ● Behavior Sensitivity ● Data Sensitivity ● Context Sensitivity ● Overspecified Software ● Sensitive Equality ● Fragile Fixture
  82. 82. Context Sensitivity ● Symptoms ● 成功していたテストが突然失敗し始める – Erratic Test との違いは、再現性があること ● Root Cause ● 時刻や日付に依存している ● SUT が他システムや OS に依存している ● 本当にユニットテストになっているか確認しよう。テス ト範囲が広すぎて Context Sensitivity に陥っていない か ● 広すぎると誰かが DOC を変更しただけでもテストは失 敗する
  83. 83. Context Sensitivity (2) ● Root Cause (Cont'd) ● 時刻や日付に依存しているコードがあるか ● 他システムからの入力に依存しているコードがある か ● 実は問題が発生したりしなかったりするようなら Erratic Test の知識を生かすべし ● Possible Solution ● Test Stub (p529) に置き換える ● 時刻依存なら Virtual Clock [VCTP] に置き換える – (Fowler の FakeClock もみてみよう)
  84. 84. Fragile Test Causes ● Fragile Test ● Interface Sensitivity ● Behavior Sensitivity ● Data Sensitivity ● Context Sensitivity ● Overspecified Software ● Sensitive Equality ● Fragile Fixture
  85. 85. Overspecified Software ● テストが SUT がどう振る舞うべきかについて 「過剰に」記述されている ● Test Double を使った Behavior Verification でよ く発生する ● Mock Object の使いすぎ ● 原因は「What」ではなく「How」をテストで 記述してしまっていること ● 実装依存になりすぎている ● Use the Front Door First !! (p40)
  86. 86. Fragile Test Causes ● Fragile Test ● Interface Sensitivity ● Behavior Sensitivity ● Data Sensitivity ● Context Sensitivity ● Overspecified Software ● Sensitive Equality ● Fragile Fixture
  87. 87. Sensitive Equality ● オブジェクトを文字列に変換して expected と actual を比較している ● 関係ない部分の比較で失敗しやすい ● interface の semantics が変更されていると いう意味では Interface Sensitivity とも言え る(?) ● オブジェクトの文字列変換による比較は災いの 素 (Gerard) ● まさーるさんは文字列比較を奨めていたが…
  88. 88. Fragile Test Causes ● Fragile Test ● Interface Sensitivity ● Behavior Sensitivity ● Data Sensitivity ● Context Sensitivity ● Overspecified Software ● Sensitive Equality ● Fragile Fixture
  89. 89. Fragile Fixture ● 新しいテストのために Standard Fixture を編 集したら、全然違うテストが失敗した ● Data Sensitivity や Context Sensitivity の変種 ● Fixture の性質の違い
  90. 90. ご清聴 ありがとう ございました

×