SlideShare ist ein Scribd-Unternehmen logo
1 von 90
Downloaden Sie, um offline zu lesen
Chapter 16.
Behavior Smells
Smells in This Chapter
●
    Assertion Roulette
●
    Erratic Test
●
    Fragile Test
●
    Frequent Debugging
●
    Manual Intervention
●
    Slow Tests
Assertion Roulette
Assertion Roulette (1)
●
    初出
    ●
        XP2001 “Refactoring Test Code”
●
    Symptoms
    ●
        テスト失敗時に、どの assertion が失敗したのかよ
        く分からない
●
    Impact
    ●   CI 中にテストが Assertion Roulette が発現した場
        合には解析が難しい。手元のマシンで再現できない
        時はさらに時間を食うことになる
Assertion Roulette (2)
●
    Causes
    ●
        Eager Test
        –   ひとつのテストで機能を検証しすぎている
    ●
        Missing Assertion Message
        –   アサーションメッセージが無い
Smells in This Chapter
●
    Assertion Roulette
    ●
        Eager Test
    ●
        Missing Assertion Message
●
    Erratic Test
●
    Fragile Test
●
    Frequent Debugging
●
    Manual Intervention
●
    Slow Tests
Eager Test (1)
●
    Symptoms
    ●
        ひとつのテストが SUT の複数のメソッドをテスト
        している
    ●
        ひとつのテストが SUT の同じメソッドを fixture
        setup logic や assertion などバラバラな場所から
        複数回呼んでいる
    ●
        テスト技術者がテストフレームワークを改造して
        assertion が失敗してもその行以降を実行させよう
        とする
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());
  }
}
Eager Test (2)
●
    Root Cause
    ●
        テストの中で多くの検証を行って (意図的であるに
        しろ無いにしろ) テストの数を最小にしようとする
        こと
        –   手動テストにおいては一度にたくさんの要素をテストす
            るのは良いこととされているが、完全自動化されたテス
            トにおいては悪手
    ●
        多くのステップを必要とする Customer Test を
        xUnit を使って行おうとすること
Eager Test (3)
●
    Possible Solution
    ●
        Single-Condition Test (p45) に分解する
        –   Extract Method [Fowler]
        –   ひとつひとつのテスト要素毎にコピーして不要な部分を
            削除
    ●
        Creation Method (p415)
        –   Fixture を setup したり SUT を特定の状態にする部分
            をメソッドに切り出す
        –   Lean on Compiler [WEwLC] 使おう
Eager Test (4)
●
    Customer Test を xUnit で行っている場合
        –   テストシナリオが進むに応じて複雑な状態がテスト内で
            作り出されていく
        –   テスト後半部分を切り出すためには複雑な状態の setup
            が必要なので、なんらかの手段を講じる必要がある
    ●
        Back Door Setup (p327) を使ってテスト後半部分
        の setup を行えればテストを分割できる
        –   Defect Localization につながる
        –   テストを短くしていけば Communicate Intent (p41) へ
Smells in This Chapter
●
    Assertion Roulette
    ●
        Eager Test
    ●
        Missing Assertion Message
●
    Erratic Test
●
    Fragile Test
●
    Frequent Debugging
●
    Manual Intervention
●
    Slow Tests
Missing Assertion Message (1)
●
    Symptoms
    ●
        テスト失敗時に、どの assertion が失敗したのか
        よく分からない
Missing Assertion Message (2)
●
    Root Cause
    ●
        Assertion Method (p362) が
        –   同じ Assertion Method が複数回使われている
        –   Assertion Message (p370) 無しで書かれている
    ●
        コマンドラインからテストを実行したり、開発環境
        とテストコードが統合されていない時にどこで失敗
        したか分からず困る
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 では?
Missing Assertion Message (3)
●
    Possible Solution
    ●
        GUI のある IDE の場合はスタックトレースをクリックして
        飛んで、ブレークポイントつけて再実行できたりする
    ●
        コマンドラインで実行している場合には GUI ランナーや
        IDE で実行して落ちている assertion を見つけよう
    ●
        それらもダメな場合は行番号を追ったり、もっと深追いし
        なければならない
    ●
        そんな頑張らずに、数字でもいいから Assertion Message
        入れよう (そういえばひがさんはそうしてた)
Smells in This Chapter
●
    Assertion Roulette
●
    Erratic Test
●
    Fragile Test
●
    Frequent Debugging
●
    Manual Intervention
●
    Slow Tests
Erratic Test
erratic
【名】
 1. 変人、奇人
 2. 《地学》迷子石◆【同】erratic boulder


【形】
 1. 〔人の言動が〕とっぴな、風変わりな、異常な、常軌を逸した
 2. 一貫性のない、不安定な、一定しない、出来不出来がある、不
規則な
 3. 《地学》〔石などが氷河で〕漂移した
Erratic Test (1)
●
    成功したり失敗したり、動きが一定でない
●
    Symptoms
    ●
        いつ実行したかや誰が実行したかによってテストの
        結果が異なる
    ●
        同じ Test Runner で実行しても結果がバラバラな
        ことがある
Erratic Test (2)
●
    Impact
    ●
        いつも Test Suite を緑にしたいので Erratic Test
        を suite から外し、Lost Test (p268) につながる
    ●
        Suite に入れたままにしたらしたで、他のテストで
        赤が出たときに気づかなかったりする
Erratic Test (3)
●
    Troubleshooting Advice
    ●
        原因がいろいろあるので手強い
    ●
        簡単に見つからない場合にはデータを定期的に採っ
        て調べる必要がある
        –   どこで成功し、どこで失敗したか
        –   全部のテストを実行したのか、一部を実行したのか
        –   同じ行を何度も実行した時に振る舞いが変わったか
        –   複数の Test Runner を同時に実行した時に振る舞いが
            変わったか
Erratic Test (4)
●
    Troubleshooting Advice
    ●
        原因がいろいろあるので手強い
    ●
        簡単に見つからない場合にはデータを定期的に採っ
        て調べる必要がある
        –   どこで成功し、どこで失敗したか
        –   全部のテストを実行したのか、一部を実行したのか
        –   同じ行を何度も実行した時に振る舞いが変わったか
        –   複数の Test Runner を同時に実行した時に振る舞いが
            変わったか
    ●
        データが採れたら次のページの切り分け図へ
Erratic Test (5)
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
Erratic Test Causes
●
    Erratic Test
    ●
        Interacting Tests
    ●
        Interacting Test Suites
    ●
        Lonely Test
    ●
        Resource Leakage
    ●
        Resource Optimism
    ●
        Unrepeatable Test
    ●
        Test Run War
    ●
        Nondeterministic Test
Interacting Tests (1)
●
    テストが他のテストに何らかの形で依存してい
    る
●
    バリエーション
    ●
        Interacting Test Suite
    ●
        Lonely Test
Interacting Tests (2)
●
    Symptoms
    ●
        独立して動かすときには成功しているテストが以下
        の状況下で失敗する
        –   他のテストが suite に追加 / 削除されたとき
        –   Suite の他のテストが失敗 / 成功したとき
        –   テスト自身、もしくは他のテストのファイル名が変更さ
            れたとき
        –   Test Runner の新バージョンがインストールされたとき
Interacting Tests (3)
●
    Root Cause
    ●
        多くの場合、 Shared Fixture (p317) を使ってい
        てかつ他のテストの (Shared Fixture への) 出力に
        依存しているために発生する
    ●
        二つの側面から説明できる
        –   The mechanism of interaction
        –   The reason of interaction
Interacting Tests (4)
●
    The Mechanism of interaction
    ●
        テスト (インスタンス) の寿命より長いものを使う
        ときに起こる
        –   データベース
        –   static 変数
    ●
        やめておいたほうがいいもの
        –   Singleton [GoF]
        –   Registry [PofEAA]
Interacting Tests (5)
●
    The Reason of interaction
    ●
        他のテストの fixture setup phase で作られる
        fixture に依存している
    ●
        他のテストが SUT に与える変化に依存している
    ●
        相互排他に行うべきテストを同時に行うことによる
        競合
Interacting Tests (5)
●   依存関係が終わるとき
    ●   依存している他のテストが
        –   suite からいなくなる
        –   SUT を変化させなくなる
        –   SUT を変化させる際に失敗するようになる
        –   改名などにより、テスト実行の順番が後ろになる
●   競合が始まるとき
    ●   競合しているテストが
        –   suite に加わる
        –   初めて成功した時点
        –   テスト実行の順番が前になったとき
Interacting Tests (6)
●
    テスト対象自体は正しいのに失敗するようにな
    るので、 “false-positive” になる。


●
    一般論としてテスト実行順に依存するのは良く
    ない
    ●
        xUnit ファミリーは実行順を保証しない
    ●
        TestNG は保証する
Interacting Tests (7)
●
    Possible Solution
    ●
        Fresh Fixture (p311)
        –   もっとも望ましい
    ●
        Shared Fixture を使いたい場合は
        –   Immutable Shared Fixture
    ●
        他のテストが作成するオブジェクトに依存している
        時は
        –   両方のテストに Lazy Setup (p435) を書く
             ●
                 コードが重複する場合は
                 –   Creation Method (p415)
                 –   Test Helper (p643)
Interacting Tests (8)
●
    Possible Solution (Cont'd)
    ●
        テストで作成されたものが残っていることによる競
        合には
        –   Automated Fixture Teardown (p503)


●
    テストの依存を見つける方法
    ●
        いつもと違う順番で実行してみる
        –   すべてのテストを逆順に実行してみる
    ●
        普段から常にバラバラの順番でテストを実行するよ
        うにしておくと事故を防げて良い
Erratic Test Causes
●
    Erratic Test
    ●
        Interacting Tests
    ●
        Interacting Test Suites
    ●
        Lonely Test
    ●
        Resource Leakage
    ●
        Resource Optimism
    ●
        Unrepeatable Test
    ●
        Test Run War
    ●
        Nondeterministic Test
Interacting Test Suites (1)
●
    Symptoms
    ●
        Suite 単体では成功するが、 Suite の Suite とい
        う構成にすると失敗する


●
    Root Cause
    ●
        よくあるのは、同じリソースを Suite が作成しよ
        うとし、後から実行された Suite のほうが失敗す
        るケース
Interacting Test Suites (2)
●
    探すには
    ●
        失敗したテストを見る
    ●
        それでも分からない時には
        –   成功している方の Suite からテストを一つずつ取り除く
             ●
                 失敗しなくなったときに取り除いたテストが依存元
    ●
        場所はどこか
        –   Shared Fixture
        –   Test Method 内
        –   Setup method
        –   Test Utility
Interacting Test Suites (3)
●
    Root Cause (Cont'd)
    ●
        依存しあっているのは一つのテストとは限らない
    ●
        テストケースではなく Suite Fixture Setup や
        Setup Decorator が引き金となっているかもしれ
        ない
●
    NUnit についてまたいろいろ書いているが割愛
Interacting Test Suites (4)
●
    Possible Solution
    ●
        一番いいのは全部 Fresh Fixture にすること
    ●
        Fresh Fixture にするのが難しければ Immutable
        Shared Fixture
    ●
        データベースに残っている残骸が問題なら
        Automated Teardown
Erratic Test Causes
●
    Erratic Test
    ●
        Interacting Tests
    ●
        Interacting Test Suites
    ●
        Lonely Test
    ●
        Resource Leakage
    ●
        Resource Optimism
    ●
        Unrepeatable Test
    ●
        Test Run War
    ●
        Nondeterministic Test
Lonely Test (1)
●
    Interacting Tests の特殊例
●
    Suite の一部としては実行成功するが、単独で
    は動かない
    ●
        他のテストの触った Shared Fixture に依存してい
        る
        –   Chained Tests
        –   Suite-level fixture setup
Erratic Test Causes
●
    Erratic Test
    ●
        Interacting Tests
    ●
        Interacting Test Suites
    ●
        Lonely Test
    ●
        Resource Leakage
    ●
        Resource Optimism
    ●
        Unrepeatable Test
    ●
        Test Run War
    ●
        Nondeterministic Test
Resource Leakage (1)
●   Symptoms
    ●   テストがだんだん遅くなり、ついには失敗しだすように
        なる
    ●   Test Runner / SUT / Database Sandbox(p650) をク
        リーンアップするとテストが通るようになる
●   Root Cause
    ●   有限リソースをテストが消費し、それの開放に失敗して
        いる
    ●   テストがどんどん遅くなる
    ●   テストを連続して続けるとリソースが使い尽くされ、後
        続のテストが失敗し始める
Resource Leakage (2)
●
    Root Cause (Cont'd)
    ●
        SUT がリソースの開放に失敗している
        –   これが判明したら、直すのも難しくない
    ●
        テストが fixture setup でリソースを消費し、開
        放に失敗している
Resource Leakage (3)
●
    Possible Solution
    ●
        SUT がリソースを開放していないとき
        –   テストは仕事をきちんとしているので SUT のバグを直
            すべし
    ●
        テスト失敗時にリソース開放に失敗している場合
        –   Guaranteed In-line Teardown (p509)
        –   Automated Teardown
●
    リソースプールのサイズを 1 にするのがいい
    ●
        問題がある場合にはテストがすぐ失敗するようにな
        り、気づきやすい
Erratic Test Causes
●
    Erratic Test
    ●
        Interacting Tests
    ●
        Interacting Test Suites
    ●
        Lonely Test
    ●
        Resource Leakage
    ●
        Resource Optimism
    ●
        Unrepeatable Test
    ●
        Test Run War
    ●
        Nondeterministic Test
Resource Optimism
●
    Symptoms
    ●
        ある環境下で動くテストが他の環境下で失敗する
●
    Root Cause
    ●
        ある環境に存在するリソースが他の環境で不在
●
    Possible Solution
    ●
        可能なら、 Fresh Fixture をテストから毎回作成す
        るようにする
        –   相対パスを使ってファイルを生成するなど
    ●
        外部リソースを使わなければならない場合には SCM
        に入れることも視野に入れる
Erratic Test Causes
●
    Erratic Test
    ●
        Interacting Tests
    ●
        Interacting Test Suites
    ●
        Lonely Test
    ●
        Resource Leakage
    ●
        Resource Optimism
    ●
        Unrepeatable Test
    ●
        Test Run War
    ●
        Nondeterministic Test
Unrepeatable Test (1)
●
    Symptoms
    ●
        あるテストがテスト群の先頭にある場合はテストが
        成功し、後続にある場合は失敗する。もしくはその
        逆。
        –   Pass-Fail-Fail
        –   Fail-Pass-Pass
Unrepeatable Test (2)
●
    Root Cause
    ●
        (意図の有無に関わらず) Shared Fixture の使用
        –   Prebuilt Fixture を使っている場合にはDatabase
    ●
        Sandbox を使っていても、同一の開発者が同一の
        テストランナーを使ったときは発生する
    ●
        Lazy Setup を使っている場合には、 fixture が
        class 変数を使いつづけたりする
Unrepeatable Test (3)
●
    Possible Solution
    ●
        Fresh Fixture!
        –   Database Sandbox すら生ぬるい
    ●
        Fake Database (p551)
    ●
        共有 Database を使わなければならない場合には
        Distinct Generated Values (p723)
    ●
        Automated Teardown
Erratic Test Causes
●
    Erratic Test
    ●
        Interacting Tests
    ●
        Interacting Test Suites
    ●
        Lonely Test
    ●
        Resource Leakage
    ●
        Resource Optimism
    ●
        Unrepeatable Test
    ●
        Test Run War
    ●
        Nondeterministic Test
Test Run War (1)
●
    Symptoms
    ●
        一人でテストを実行する時はテストが成功するが、
        複数人が同時にテストを実行すると失敗する
●
    Impact
    ●
        カットオフ間近に発生しがちだからイライラする!
    ●
        「テストが落ちたら最後の変更を疑え」ルールが機
        能しなくなる
Test Run War (2)
●
    Root Cause
    ●
        Shared Fixture (Database)
        –   行の UPDATE / DELETE / SELECT などの競合
        –   悲観ロック
    ●
        Shared Fixture (File)
        –   既に他の人がファイルを開いているなど
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 の根本解決にはならないが、確率が減る
Erratic Test Causes
●
    Erratic Test
    ●
        Interacting Tests
    ●
        Interacting Test Suites
    ●
        Lonely Test
    ●
        Resource Leakage
    ●
        Resource Optimism
    ●
        Unrepeatable Test
    ●
        Test Run War
    ●
        Nondeterministic Test
Nondeterministic Test (1)
●
    Symptoms
    ●
        テストがランダムに失敗する
        –   人や環境、同時実行にも関係なさそう
    ●
        複数の Nondeterministic Test が suite にあると
        問題判別が難しい
●
    Impact
    ●
        デバッグに時間がかかりすぎるし、イライラする
Nondeterministic Test (2)
●
    Root Cause
    ●
        テスト毎に異なる値を使うことによって発生する
        –   ただし、異なる値を使うこと自体は悪いことではない。
            (例 : Distinct Generated Value)
        –   テスト対象アルゴリズムへの入力にランダムな値を使う
            ときに問題が発生する
            ●
                Integer の負数や臨界値など
            ●
                長さ限界の文字列など
    ●
        ランダム値を使うことは悪くないように思えるが、
        カバレッジへの信頼とテストの repeatabilty が下
        がる
Nondeterministic Test (3)
●
    Root Cause (Cont'd)
    ●
        Conditional Test Logic の使用がテストにランダ
        ムさをもたらす
        –   テスト毎にテスト実行パスが異なる
Nondeterministic Test (4)
●
    Possible Solution
    ●
        Conditional Test Logic を取り除いて Linear に実
        行されるようにする
    ●
        ランダム値の使用を止めて deterministic な値を
        使うようにする
    ●
        臨界値や同値分割を使う
    ●
        テストが重複し始めたら
        –   Parameterized Test (p607)
        –   Data-Driven Test (p288)
Smells in This Chapter
●
    Assertion Roulette
●
    Erratic Test
●
    Fragile Test
●
    Frequent Debugging
●
    Manual Intervention
●
    Slow Tests
Fragile Test
fragile
【形】
 1. 壊れやすい、もろい、割れやすい、脆弱な、傷
(が)付きやすい、駄目になりやすい、危うい、軽
い、か弱い、はかない、きゃしゃな
  2. 実質のない、不十分な
  3. 束の間の、逼迫した
  4. 虚弱な、元気がない、調子が悪い
Fragile Test (1)
●
    Symptoms
    ●
        全然関係ないと思っていた部分の修正で、テストが
        コンパイル/実行に失敗し始める
        –   ときには production code に手を触れていないのに失敗
            し始めることも
    ●
        テスト自動化に頑張っていればいるほど、”four
        sensitivities” (4 つの過敏症) に引っかかりやすく
        なる
Fragile Test (2)
●
    Impact
    ●
        変更を行う際にあちこちのテストを見なければなら
        ないため、テストのメンテナンスコストが上がる
    ●
        Incremental delivery を行う XP のようなプロセ
        スでは、テストのメンテナンスコスト増は致命傷に
        なりうる
Fragile Test (3)
●
    Troubleshooting Advice
    ●
        「落ちたテストに共通点は無いか?」と自問しよう
        –   テストと SUT の結合点が見えてくる
●
    4 sensitivities
    ●
        Interface Sensitivity
        –   コンパイルに失敗する
        –   動的型付け言語では型非互換ランタイムエラー
    ●
        Behavior Sensitivity
        –   直前の変更を戻したらテストが通るようになる
Fragile Test (4)
●
    Troubleshooting Advice (Cont'd)
    ●
        Data Sensitivity
        –   直前のコード変更を戻してもテストが失敗する
            ●
                Shared Fixture を使っている or Fixture setup code を変更し
                た
    ●
        Context Sensitivity
        –   直前のコード変更を戻してもテストが失敗する
            ●
                テストコードもテストデータもいじってない
Fragile Test (5)
●
    Troubleshooting Advice (Cont'd)
    ●
        Data Sensitivity
        –   直前のコード変更を戻してもテストが失敗する
            ●
                Shared Fixture を使っている or Fixture setup code を変更し
                た
    ●
        Context Sensitivity
        –   直前のコード変更を戻してもテストが失敗する
            ●
                テストコードもテストデータもいじってない
Fragile Test (6)
Fragile Test (7)
●
    Causes
    ●
        Indirect Testing
        –   SUT に他のオブジェクトを介してアクセスしている
    ●
        Eager Tests
        –   テストで検証をしすぎている
    ●
        SUT の結合度が強すぎることの現れ
        –   そもそも小さい単位でテストするのが難しい SUT なの
            かもしれない (Hard-to-Test Code)
        –   Test Doubles を使い慣れていないだけかもしれない
Fragile Test Causes
●
    Fragile Test
    ●
        Interface Sensitivity
    ●
        Behavior Sensitivity
    ●
        Data Sensitivity
    ●
        Context Sensitivity
    ●
        Overspecified Software
    ●
        Sensitive Equality
    ●
        Fragile Fixture
Interface Sensitivity
●
    Symptoms
    ●
        SUT が変更されるとテストのコンパイル/実行に失
        敗する
        –   静的型付け言語の場合はテストコンパイル失敗
        –   動的型付け言語の場合はテスト実行失敗
        –   (変種) GUI 経由で Recorded Test を行っている場合
            は、 UI 変更でテスト実行に失敗するとか
Interface Sensitivity (2)
●
    Possible Solution
    ●
        原因はわかりやすいことが多い
        –   コンパイル/テスト失敗する場所が問題箇所
        –   結局変更点が引き金になっていることが多い
    ●
        内部で使われる interface の場合には SUT API
        Encapsulation
        –   テスト用の Higher-Level Language (p41) を組む
             ●
                 Test Utility Methods
             ●
                 Creation Methods
    ●
        “公布済み interface” の場合にはきちんと管理する
        しかない
Fragile Test Causes
●
    Fragile Test
    ●
        Interface Sensitivity
    ●
        Behavior Sensitivity
    ●
        Data Sensitivity
    ●
        Context Sensitivity
    ●
        Overspecified Software
    ●
        Sensitive Equality
    ●
        Fragile Fixture
Behavior Sensitivity
●   Symptoms
    ●   SUT が変更されると関係ない部分のテストの実行に失
        敗する
●   Root Cause
    ●   テストが失敗する事自体は悪くない。自動テストはそ
        のためにある。
    ●   Behavior Sensitivity になるのは、関係ないと思って
        いたテストの以下の部分が失敗するとき
        –   Pre-test state setup (fixture setup)
        –   Post-test state verification
        –   Tear down (fixture teardown)
Behavior Sensitivity (2)
●
    Possible Solution
    ●
        Fixture setup に失敗しているとき
        –   Creation Method
    ●
        State Verification に失敗しているとき
        –   Custom Assertion
        –   Verification Method
    ●
        (fixture teardown が無いが…たぶん)
        –   Test Utility Method
        –   Delegated Teardown
Fragile Test Causes
●
    Fragile Test
    ●
        Interface Sensitivity
    ●
        Behavior Sensitivity
    ●
        Data Sensitivity
    ●
        Context Sensitivity
    ●
        Overspecified Software
    ●
        Sensitive Equality
    ●
        Fragile Fixture
Data Sensitivity
●
    Symptoms
    ●
        テストデータが変更されるとテストの実行に失敗す
        る
        –   既存テストデータの追加、更新、削除
        –   Standard Fixture のセットアップコードが変更された
        –   テスト実行前に Shared Fixture が変更されている
●
    Root Cause
    ●
        データが変わっている!
        –   検索に余計に引っかかるとか
        –   無くなっているとか
Data Sensitivity (2)
●
    Possible Solution
    ●
        多くの場合 result verification で発生する
        –   Verification logic を見直す
    ●
        一番良いのは Fresh Fixture
    ●
        Database Partitioning Scheme
    ●
        Delta Assertions
Fragile Test Causes
●
    Fragile Test
    ●
        Interface Sensitivity
    ●
        Behavior Sensitivity
    ●
        Data Sensitivity
    ●
        Context Sensitivity
    ●
        Overspecified Software
    ●
        Sensitive Equality
    ●
        Fragile Fixture
Context Sensitivity
●   Symptoms
    ●   成功していたテストが突然失敗し始める
        –   Erratic Test との違いは、再現性があること
●   Root Cause
    ●   時刻や日付に依存している
    ●   SUT が他システムや OS に依存している
    ●   本当にユニットテストになっているか確認しよう。テス
        ト範囲が広すぎて Context Sensitivity に陥っていない
        か
    ●   広すぎると誰かが DOC を変更しただけでもテストは失
        敗する
Context Sensitivity (2)
●
    Root Cause (Cont'd)
    ●
        時刻や日付に依存しているコードがあるか
    ●
        他システムからの入力に依存しているコードがある
        か
    ●
        実は問題が発生したりしなかったりするようなら
        Erratic Test の知識を生かすべし
●
    Possible Solution
    ●
        Test Stub (p529) に置き換える
    ●
        時刻依存なら Virtual Clock [VCTP] に置き換える
        –   (Fowler の FakeClock もみてみよう)
Fragile Test Causes
●
    Fragile Test
    ●
        Interface Sensitivity
    ●
        Behavior Sensitivity
    ●
        Data Sensitivity
    ●
        Context Sensitivity
    ●
        Overspecified Software
    ●
        Sensitive Equality
    ●
        Fragile Fixture
Overspecified Software
●
    テストが SUT がどう振る舞うべきかについて
    「過剰に」記述されている
    ●
        Test Double を使った Behavior Verification でよ
        く発生する
    ●
        Mock Object の使いすぎ
●
    原因は「What」ではなく「How」をテストで
    記述してしまっていること
    ●
        実装依存になりすぎている
●
    Use the Front Door First !! (p40)
Fragile Test Causes
●
    Fragile Test
    ●
        Interface Sensitivity
    ●
        Behavior Sensitivity
    ●
        Data Sensitivity
    ●
        Context Sensitivity
    ●
        Overspecified Software
    ●
        Sensitive Equality
    ●
        Fragile Fixture
Sensitive Equality
●
    オブジェクトを文字列に変換して expected と
    actual を比較している
    ●
        関係ない部分の比較で失敗しやすい
●
    interface の semantics が変更されていると
    いう意味では Interface Sensitivity とも言え
    る(?)
●
    オブジェクトの文字列変換による比較は災いの
    素 (Gerard)
    ●
        まさーるさんは文字列比較を奨めていたが…
Fragile Test Causes
●
    Fragile Test
    ●
        Interface Sensitivity
    ●
        Behavior Sensitivity
    ●
        Data Sensitivity
    ●
        Context Sensitivity
    ●
        Overspecified Software
    ●
        Sensitive Equality
    ●
        Fragile Fixture
Fragile Fixture
●
    新しいテストのために Standard Fixture を編
    集したら、全然違うテストが失敗した
    ●
        Data Sensitivity や Context Sensitivity の変種
    ●
        Fixture の性質の違い
ご清聴
ありがとう
ございました

Weitere ähnliche Inhalte

Was ist angesagt?

Introduction to boost test
Introduction to boost testIntroduction to boost test
Introduction to boost testKohsuke Yuasa
 
Unit testで定時帰宅!
Unit testで定時帰宅!Unit testで定時帰宅!
Unit testで定時帰宅!Funato Takashi
 
xUnit Test Patterns - Chapter11
xUnit Test Patterns - Chapter11xUnit Test Patterns - Chapter11
xUnit Test Patterns - Chapter11Takuto Wada
 
Try_to_writecode_practicaltest #atest_hack
Try_to_writecode_practicaltest #atest_hackTry_to_writecode_practicaltest #atest_hack
Try_to_writecode_practicaltest #atest_hackkimukou_26 Kimukou
 
20161203 selenium adventcalender
20161203 selenium adventcalender20161203 selenium adventcalender
20161203 selenium adventcalenderNaoya Kojima
 
Apache Wicketのユニットテスト機能
Apache Wicketのユニットテスト機能Apache Wicketのユニットテスト機能
Apache Wicketのユニットテスト機能Hiroto Yamakawa
 
Code complete ch22_developper_test
Code complete ch22_developper_testCode complete ch22_developper_test
Code complete ch22_developper_testSho Shimauchi
 
第4回勉強会 単体テストのすすめ
第4回勉強会 単体テストのすすめ第4回勉強会 単体テストのすすめ
第4回勉強会 単体テストのすすめhakoika-itwg
 
はこだてIKA 第4回勉強会 単体テスト
はこだてIKA 第4回勉強会 単体テストはこだてIKA 第4回勉強会 単体テスト
はこだてIKA 第4回勉強会 単体テストSeiji KOMATSU
 
ゆもつよ博士論文説明資料公開
ゆもつよ博士論文説明資料公開ゆもつよ博士論文説明資料公開
ゆもつよ博士論文説明資料公開Tsuyoshi Yumoto
 
Ruby初級者向けレッスン 第46回 ─── Test::Unit
Ruby初級者向けレッスン 第46回 ─── Test::UnitRuby初級者向けレッスン 第46回 ─── Test::Unit
Ruby初級者向けレッスン 第46回 ─── Test::Unithigaki
 
JUnit実践入門 xUnitTestPatternsで学ぶユニットテスト
JUnit実践入門 xUnitTestPatternsで学ぶユニットテストJUnit実践入門 xUnitTestPatternsで学ぶユニットテスト
JUnit実践入門 xUnitTestPatternsで学ぶユニットテストShuji Watanabe
 
111008 silverlight square_datavalidation
111008 silverlight square_datavalidation111008 silverlight square_datavalidation
111008 silverlight square_datavalidationTakayoshi Tanaka
 
プログラマーのためのテスト手法
プログラマーのためのテスト手法プログラマーのためのテスト手法
プログラマーのためのテスト手法myukidi
 
TDDワークショップ(第2回)
TDDワークショップ(第2回)TDDワークショップ(第2回)
TDDワークショップ(第2回)Yoshihiro Furukawa
 

Was ist angesagt? (16)

Introduction to boost test
Introduction to boost testIntroduction to boost test
Introduction to boost test
 
Unit testで定時帰宅!
Unit testで定時帰宅!Unit testで定時帰宅!
Unit testで定時帰宅!
 
Junit4
Junit4Junit4
Junit4
 
xUnit Test Patterns - Chapter11
xUnit Test Patterns - Chapter11xUnit Test Patterns - Chapter11
xUnit Test Patterns - Chapter11
 
Try_to_writecode_practicaltest #atest_hack
Try_to_writecode_practicaltest #atest_hackTry_to_writecode_practicaltest #atest_hack
Try_to_writecode_practicaltest #atest_hack
 
20161203 selenium adventcalender
20161203 selenium adventcalender20161203 selenium adventcalender
20161203 selenium adventcalender
 
Apache Wicketのユニットテスト機能
Apache Wicketのユニットテスト機能Apache Wicketのユニットテスト機能
Apache Wicketのユニットテスト機能
 
Code complete ch22_developper_test
Code complete ch22_developper_testCode complete ch22_developper_test
Code complete ch22_developper_test
 
第4回勉強会 単体テストのすすめ
第4回勉強会 単体テストのすすめ第4回勉強会 単体テストのすすめ
第4回勉強会 単体テストのすすめ
 
はこだてIKA 第4回勉強会 単体テスト
はこだてIKA 第4回勉強会 単体テストはこだてIKA 第4回勉強会 単体テスト
はこだてIKA 第4回勉強会 単体テスト
 
ゆもつよ博士論文説明資料公開
ゆもつよ博士論文説明資料公開ゆもつよ博士論文説明資料公開
ゆもつよ博士論文説明資料公開
 
Ruby初級者向けレッスン 第46回 ─── Test::Unit
Ruby初級者向けレッスン 第46回 ─── Test::UnitRuby初級者向けレッスン 第46回 ─── Test::Unit
Ruby初級者向けレッスン 第46回 ─── Test::Unit
 
JUnit実践入門 xUnitTestPatternsで学ぶユニットテスト
JUnit実践入門 xUnitTestPatternsで学ぶユニットテストJUnit実践入門 xUnitTestPatternsで学ぶユニットテスト
JUnit実践入門 xUnitTestPatternsで学ぶユニットテスト
 
111008 silverlight square_datavalidation
111008 silverlight square_datavalidation111008 silverlight square_datavalidation
111008 silverlight square_datavalidation
 
プログラマーのためのテスト手法
プログラマーのためのテスト手法プログラマーのためのテスト手法
プログラマーのためのテスト手法
 
TDDワークショップ(第2回)
TDDワークショップ(第2回)TDDワークショップ(第2回)
TDDワークショップ(第2回)
 

Andere mochten auch

組織にテストを書く文化を根付かせる戦略と戦術
組織にテストを書く文化を根付かせる戦略と戦術組織にテストを書く文化を根付かせる戦略と戦術
組織にテストを書く文化を根付かせる戦略と戦術Takuto Wada
 
UnitTestのためのクラス設計
UnitTestのためのクラス設計UnitTestのためのクラス設計
UnitTestのためのクラス設計Takeshi Ishida
 
WWDC 2016の概観
WWDC 2016の概観WWDC 2016の概観
WWDC 2016の概観Yuta Hoshino
 
テスト駆動開発の進化
テスト駆動開発の進化テスト駆動開発の進化
テスト駆動開発の進化Yukei Wachi
 
テスト駆動開発入門
テスト駆動開発入門テスト駆動開発入門
テスト駆動開発入門Shuji Watanabe
 
テスト駆動開発のはじめ方
テスト駆動開発のはじめ方テスト駆動開発のはじめ方
テスト駆動開発のはじめ方Shuji Watanabe
 
テスト駆動開発へようこそ
テスト駆動開発へようこそテスト駆動開発へようこそ
テスト駆動開発へようこそShuji Watanabe
 
TDDBC Fukuoka Day1
TDDBC Fukuoka Day1TDDBC Fukuoka Day1
TDDBC Fukuoka Day1Takuto Wada
 
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」Takuto Wada
 
Test Yourself - テストを書くと何がどう変わるか
Test Yourself - テストを書くと何がどう変わるかTest Yourself - テストを書くと何がどう変わるか
Test Yourself - テストを書くと何がどう変わるかTakuto Wada
 

Andere mochten auch (10)

組織にテストを書く文化を根付かせる戦略と戦術
組織にテストを書く文化を根付かせる戦略と戦術組織にテストを書く文化を根付かせる戦略と戦術
組織にテストを書く文化を根付かせる戦略と戦術
 
UnitTestのためのクラス設計
UnitTestのためのクラス設計UnitTestのためのクラス設計
UnitTestのためのクラス設計
 
WWDC 2016の概観
WWDC 2016の概観WWDC 2016の概観
WWDC 2016の概観
 
テスト駆動開発の進化
テスト駆動開発の進化テスト駆動開発の進化
テスト駆動開発の進化
 
テスト駆動開発入門
テスト駆動開発入門テスト駆動開発入門
テスト駆動開発入門
 
テスト駆動開発のはじめ方
テスト駆動開発のはじめ方テスト駆動開発のはじめ方
テスト駆動開発のはじめ方
 
テスト駆動開発へようこそ
テスト駆動開発へようこそテスト駆動開発へようこそ
テスト駆動開発へようこそ
 
TDDBC Fukuoka Day1
TDDBC Fukuoka Day1TDDBC Fukuoka Day1
TDDBC Fukuoka Day1
 
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
 
Test Yourself - テストを書くと何がどう変わるか
Test Yourself - テストを書くと何がどう変わるかTest Yourself - テストを書くと何がどう変わるか
Test Yourself - テストを書くと何がどう変わるか
 

Ähnlich wie xUnit Test Patterns - Chapter16

Xcode10での テスト周りの進化をふりかえる
Xcode10での テスト周りの進化をふりかえるXcode10での テスト周りの進化をふりかえる
Xcode10での テスト周りの進化をふりかえるToshiyuki Hirata
 
テストコードの定型化
テストコードの定型化テストコードの定型化
テストコードの定型化Shinichi Hirauchi
 
nGrinder3 : だれもが簡単にできる性能テスト
nGrinder3 : だれもが簡単にできる性能テストnGrinder3 : だれもが簡単にできる性能テスト
nGrinder3 : だれもが簡単にできる性能テストJunHo Yoon
 
Continuous delivery chapter4
Continuous delivery chapter4Continuous delivery chapter4
Continuous delivery chapter4favril1
 
タダで始めるテストファースト入門 ~ C# Express + NUnit
タダで始めるテストファースト入門 ~ C# Express + NUnitタダで始めるテストファースト入門 ~ C# Express + NUnit
タダで始めるテストファースト入門 ~ C# Express + NUnitYasuhiko Yamamoto
 
テストコードのリファクタリング
テストコードのリファクタリングテストコードのリファクタリング
テストコードのリファクタリングShuji Watanabe
 
モデル検査入門 #wacate
モデル検査入門 #wacateモデル検査入門 #wacate
モデル検査入門 #wacateKinji Akemine
 
TDD Boot Camp Tokyo for C++ 2014-01 補講
TDD Boot Camp Tokyo for C++ 2014-01 補講TDD Boot Camp Tokyo for C++ 2014-01 補講
TDD Boot Camp Tokyo for C++ 2014-01 補講Takashi Imagire
 
ソフトウェアテスト入門
ソフトウェアテスト入門ソフトウェアテスト入門
ソフトウェアテスト入門iKenji
 
ソフトウェア工学2023 11 テスト
ソフトウェア工学2023 11 テストソフトウェア工学2023 11 テスト
ソフトウェア工学2023 11 テストToru Tamaki
 
Tokyor14 - R言語でユニットテスト
Tokyor14 - R言語でユニットテストTokyor14 - R言語でユニットテスト
Tokyor14 - R言語でユニットテストYohei Sato
 
JavaのテストGroovyでいいのではないかという話
JavaのテストGroovyでいいのではないかという話JavaのテストGroovyでいいのではないかという話
JavaのテストGroovyでいいのではないかという話disc99_
 
#NagoyaTesting アジャイルなテストの見積りと計画づくり
#NagoyaTesting アジャイルなテストの見積りと計画づくり #NagoyaTesting アジャイルなテストの見積りと計画づくり
#NagoyaTesting アジャイルなテストの見積りと計画づくり kyon mm
 
アジャイルなテストの見積もりと計画作り
アジャイルなテストの見積もりと計画作りアジャイルなテストの見積もりと計画作り
アジャイルなテストの見積もりと計画作りkyon mm
 
Web技術勉強会 20111112
Web技術勉強会 20111112Web技術勉強会 20111112
Web技術勉強会 20111112龍一 田中
 
Testing processqualifylevel 2009
Testing processqualifylevel 2009Testing processqualifylevel 2009
Testing processqualifylevel 2009Shinsuke Matsuki
 
Effective Java 輪読会 第6章 項目35-37
Effective Java 輪読会 第6章 項目35-37Effective Java 輪読会 第6章 項目35-37
Effective Java 輪読会 第6章 項目35-37Appresso Engineering Team
 

Ähnlich wie xUnit Test Patterns - Chapter16 (20)

Xcode10での テスト周りの進化をふりかえる
Xcode10での テスト周りの進化をふりかえるXcode10での テスト周りの進化をふりかえる
Xcode10での テスト周りの進化をふりかえる
 
テストコードの定型化
テストコードの定型化テストコードの定型化
テストコードの定型化
 
nGrinder3 : だれもが簡単にできる性能テスト
nGrinder3 : だれもが簡単にできる性能テストnGrinder3 : だれもが簡単にできる性能テスト
nGrinder3 : だれもが簡単にできる性能テスト
 
Continuous delivery chapter4
Continuous delivery chapter4Continuous delivery chapter4
Continuous delivery chapter4
 
タダで始めるテストファースト入門 ~ C# Express + NUnit
タダで始めるテストファースト入門 ~ C# Express + NUnitタダで始めるテストファースト入門 ~ C# Express + NUnit
タダで始めるテストファースト入門 ~ C# Express + NUnit
 
テストコードのリファクタリング
テストコードのリファクタリングテストコードのリファクタリング
テストコードのリファクタリング
 
モデル検査入門 #wacate
モデル検査入門 #wacateモデル検査入門 #wacate
モデル検査入門 #wacate
 
TDD Boot Camp Tokyo for C++ 2014-01 補講
TDD Boot Camp Tokyo for C++ 2014-01 補講TDD Boot Camp Tokyo for C++ 2014-01 補講
TDD Boot Camp Tokyo for C++ 2014-01 補講
 
ソフトウェアテスト入門
ソフトウェアテスト入門ソフトウェアテスト入門
ソフトウェアテスト入門
 
ソフトウェア工学2023 11 テスト
ソフトウェア工学2023 11 テストソフトウェア工学2023 11 テスト
ソフトウェア工学2023 11 テスト
 
Tests and bugreports
Tests and bugreportsTests and bugreports
Tests and bugreports
 
Tokyor14 - R言語でユニットテスト
Tokyor14 - R言語でユニットテストTokyor14 - R言語でユニットテスト
Tokyor14 - R言語でユニットテスト
 
JavaのテストGroovyでいいのではないかという話
JavaのテストGroovyでいいのではないかという話JavaのテストGroovyでいいのではないかという話
JavaのテストGroovyでいいのではないかという話
 
Gamedevenvstudy1
Gamedevenvstudy1Gamedevenvstudy1
Gamedevenvstudy1
 
#NagoyaTesting アジャイルなテストの見積りと計画づくり
#NagoyaTesting アジャイルなテストの見積りと計画づくり #NagoyaTesting アジャイルなテストの見積りと計画づくり
#NagoyaTesting アジャイルなテストの見積りと計画づくり
 
Beyond JUnit3
Beyond JUnit3Beyond JUnit3
Beyond JUnit3
 
アジャイルなテストの見積もりと計画作り
アジャイルなテストの見積もりと計画作りアジャイルなテストの見積もりと計画作り
アジャイルなテストの見積もりと計画作り
 
Web技術勉強会 20111112
Web技術勉強会 20111112Web技術勉強会 20111112
Web技術勉強会 20111112
 
Testing processqualifylevel 2009
Testing processqualifylevel 2009Testing processqualifylevel 2009
Testing processqualifylevel 2009
 
Effective Java 輪読会 第6章 項目35-37
Effective Java 輪読会 第6章 項目35-37Effective Java 輪読会 第6章 項目35-37
Effective Java 輪読会 第6章 項目35-37
 

Mehr von Takuto Wada

OSS活動の活発さと評価の関係について
OSS活動の活発さと評価の関係についてOSS活動の活発さと評価の関係について
OSS活動の活発さと評価の関係についてTakuto Wada
 
unassert - encourage reliable programming by writing assertions in production
unassert - encourage reliable programming by writing assertions in productionunassert - encourage reliable programming by writing assertions in production
unassert - encourage reliable programming by writing assertions in productionTakuto Wada
 
OSS についてあれこれ
OSS についてあれこれOSS についてあれこれ
OSS についてあれこれTakuto Wada
 
power-assert, mechanism and philosophy
power-assert, mechanism and philosophypower-assert, mechanism and philosophy
power-assert, mechanism and philosophyTakuto Wada
 
アジャイルサムライの次に読む技術書
アジャイルサムライの次に読む技術書アジャイルサムライの次に読む技術書
アジャイルサムライの次に読む技術書Takuto Wada
 
テスト用ライブラリ power-assert
テスト用ライブラリ power-assertテスト用ライブラリ power-assert
テスト用ライブラリ power-assertTakuto Wada
 
Reviewing RESTful Web Apps
Reviewing RESTful Web AppsReviewing RESTful Web Apps
Reviewing RESTful Web AppsTakuto Wada
 
power-assert in JavaScript
power-assert in JavaScriptpower-assert in JavaScript
power-assert in JavaScriptTakuto Wada
 
TDD のこころ @ OSH2014
TDD のこころ @ OSH2014TDD のこころ @ OSH2014
TDD のこころ @ OSH2014Takuto Wada
 
テストを書く文化を育てる戦略と戦術
テストを書く文化を育てる戦略と戦術テストを書く文化を育てる戦略と戦術
テストを書く文化を育てる戦略と戦術Takuto Wada
 
私にとってのテスト
私にとってのテスト私にとってのテスト
私にとってのテストTakuto Wada
 
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)Takuto Wada
 
SQLアンチパターン - 開発者を待ち受ける25の落とし穴
SQLアンチパターン - 開発者を待ち受ける25の落とし穴SQLアンチパターン - 開発者を待ち受ける25の落とし穴
SQLアンチパターン - 開発者を待ち受ける25の落とし穴Takuto Wada
 
愛せないコードを書くには人生はあまりにも短い
愛せないコードを書くには人生はあまりにも短い愛せないコードを書くには人生はあまりにも短い
愛せないコードを書くには人生はあまりにも短いTakuto Wada
 
ペアプログラミング ホントのところ
ペアプログラミング ホントのところペアプログラミング ホントのところ
ペアプログラミング ホントのところTakuto Wada
 
RESTful Web アプリの設計レビューの話
RESTful Web アプリの設計レビューの話RESTful Web アプリの設計レビューの話
RESTful Web アプリの設計レビューの話Takuto Wada
 
例外設計における大罪
例外設計における大罪例外設計における大罪
例外設計における大罪Takuto Wada
 
js テスト放浪記
js テスト放浪記js テスト放浪記
js テスト放浪記Takuto Wada
 

Mehr von Takuto Wada (20)

OSS活動の活発さと評価の関係について
OSS活動の活発さと評価の関係についてOSS活動の活発さと評価の関係について
OSS活動の活発さと評価の関係について
 
unassert - encourage reliable programming by writing assertions in production
unassert - encourage reliable programming by writing assertions in productionunassert - encourage reliable programming by writing assertions in production
unassert - encourage reliable programming by writing assertions in production
 
OSS についてあれこれ
OSS についてあれこれOSS についてあれこれ
OSS についてあれこれ
 
power-assert, mechanism and philosophy
power-assert, mechanism and philosophypower-assert, mechanism and philosophy
power-assert, mechanism and philosophy
 
アジャイルサムライの次に読む技術書
アジャイルサムライの次に読む技術書アジャイルサムライの次に読む技術書
アジャイルサムライの次に読む技術書
 
テスト用ライブラリ power-assert
テスト用ライブラリ power-assertテスト用ライブラリ power-assert
テスト用ライブラリ power-assert
 
Reviewing RESTful Web Apps
Reviewing RESTful Web AppsReviewing RESTful Web Apps
Reviewing RESTful Web Apps
 
power-assert in JavaScript
power-assert in JavaScriptpower-assert in JavaScript
power-assert in JavaScript
 
TDD のこころ @ OSH2014
TDD のこころ @ OSH2014TDD のこころ @ OSH2014
TDD のこころ @ OSH2014
 
テストを書く文化を育てる戦略と戦術
テストを書く文化を育てる戦略と戦術テストを書く文化を育てる戦略と戦術
テストを書く文化を育てる戦略と戦術
 
私にとってのテスト
私にとってのテスト私にとってのテスト
私にとってのテスト
 
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
 
SQLアンチパターン - 開発者を待ち受ける25の落とし穴
SQLアンチパターン - 開発者を待ち受ける25の落とし穴SQLアンチパターン - 開発者を待ち受ける25の落とし穴
SQLアンチパターン - 開発者を待ち受ける25の落とし穴
 
愛せないコードを書くには人生はあまりにも短い
愛せないコードを書くには人生はあまりにも短い愛せないコードを書くには人生はあまりにも短い
愛せないコードを書くには人生はあまりにも短い
 
ペアプログラミング ホントのところ
ペアプログラミング ホントのところペアプログラミング ホントのところ
ペアプログラミング ホントのところ
 
RESTful Web アプリの設計レビューの話
RESTful Web アプリの設計レビューの話RESTful Web アプリの設計レビューの話
RESTful Web アプリの設計レビューの話
 
例外設計における大罪
例外設計における大罪例外設計における大罪
例外設計における大罪
 
TDDBC お題
TDDBC お題TDDBC お題
TDDBC お題
 
DevLOVE DDDBC
DevLOVE DDDBCDevLOVE DDDBC
DevLOVE DDDBC
 
js テスト放浪記
js テスト放浪記js テスト放浪記
js テスト放浪記
 

Kürzlich hochgeladen

クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdfクラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdfFumieNakayama
 
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)UEHARA, Tetsutaro
 
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...博三 太田
 
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)NTT DATA Technology & Innovation
 
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)Hiroshi Tomioka
 
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?akihisamiyanaga1
 
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdfAWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdfFumieNakayama
 
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineerYuki Kikuchi
 

Kürzlich hochgeladen (8)

クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdfクラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
 
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
 
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
 
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
 
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
 
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
 
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdfAWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
 
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
 

xUnit Test Patterns - Chapter16

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