90
Chapter 16. Behavior Smells

xUnit Test Patterns - Chapter16

Embed Size (px)

DESCRIPTION

handout for xUnit Test Patterns Reading Group Japan

Citation preview

Page 1: xUnit Test Patterns - Chapter16

Chapter 16.Behavior Smells

Page 2: xUnit Test Patterns - Chapter16

Smells in This Chapter

● Assertion Roulette● Erratic Test● Fragile Test● Frequent Debugging● Manual Intervention● Slow Tests

Page 3: xUnit Test Patterns - Chapter16

Assertion Roulette

Page 4: xUnit Test Patterns - Chapter16

Assertion Roulette (1)

● 初出● XP2001 “Refactoring Test Code”

● Symptoms● テスト失敗時に、どの assertion が失敗したのかよ

く分からない● Impact

● CI 中にテストが Assertion Roulette が発現した場合には解析が難しい。手元のマシンで再現できない時はさらに時間を食うことになる

Page 5: xUnit Test Patterns - Chapter16

Assertion Roulette (2)

● Causes● Eager Test

– ひとつのテストで機能を検証しすぎている● Missing Assertion Message

– アサーションメッセージが無い

Page 6: xUnit Test Patterns - Chapter16

Smells in This Chapter

● Assertion Roulette● Eager Test● Missing Assertion Message

● Erratic Test● Fragile Test● Frequent Debugging● Manual Intervention● Slow Tests

Page 7: xUnit Test Patterns - Chapter16

Eager Test (1)

● Symptoms● ひとつのテストが SUT の複数のメソッドをテスト

している● ひとつのテストが SUT の同じメソッドを fixture

setup logic や assertion などバラバラな場所から複数回呼んでいる

● テスト技術者がテストフレームワークを改造して assertion が失敗してもその行以降を実行させようとする

Page 8: xUnit Test Patterns - Chapter16

      

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()); } }

Page 9: xUnit Test Patterns - Chapter16

Eager Test (2)

● Root Cause● テストの中で多くの検証を行って (意図的であるに

しろ無いにしろ) テストの数を最小にしようとすること– 手動テストにおいては一度にたくさんの要素をテストす

るのは良いこととされているが、完全自動化されたテストにおいては悪手

● 多くのステップを必要とする Customer Test を xUnit を使って行おうとすること

Page 10: xUnit Test Patterns - Chapter16

Eager Test (3)

● Possible Solution● Single-Condition Test (p45) に分解する

– Extract Method [Fowler]– ひとつひとつのテスト要素毎にコピーして不要な部分を

削除● Creation Method (p415)

– Fixture を setup したり SUT を特定の状態にする部分をメソッドに切り出す

– Lean on Compiler [WEwLC] 使おう

Page 11: xUnit Test Patterns - Chapter16

Eager Test (4)

● Customer Test を xUnit で行っている場合– テストシナリオが進むに応じて複雑な状態がテスト内で

作り出されていく– テスト後半部分を切り出すためには複雑な状態の setup

が必要なので、なんらかの手段を講じる必要がある● Back Door Setup (p327) を使ってテスト後半部分

の setup を行えればテストを分割できる– Defect Localization につながる– テストを短くしていけば Communicate Intent (p41) へ

Page 12: xUnit Test Patterns - Chapter16

Smells in This Chapter

● Assertion Roulette● Eager Test● Missing Assertion Message

● Erratic Test● Fragile Test● Frequent Debugging● Manual Intervention● Slow Tests

Page 13: xUnit Test Patterns - Chapter16

Missing Assertion Message (1)

● Symptoms● テスト失敗時に、どの assertion が失敗したのか

よく分からない

Page 14: xUnit Test Patterns - Chapter16

Missing Assertion Message (2)

● Root Cause● Assertion Method (p362) が

– 同じ Assertion Method が複数回使われている– Assertion Message (p370) 無しで書かれている

● コマンドラインからテストを実行したり、開発環境とテストコードが統合されていない時にどこで失敗したか分からず困る

Page 15: xUnit Test Patterns - Chapter16

      

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 では?

Page 16: xUnit Test Patterns - Chapter16

Missing Assertion Message (3)

● Possible Solution● GUI のある IDE の場合はスタックトレースをクリックして

飛んで、ブレークポイントつけて再実行できたりする ● コマンドラインで実行している場合には GUI ランナーや

IDE で実行して落ちている assertion を見つけよう● それらもダメな場合は行番号を追ったり、もっと深追いし

なければならない● そんな頑張らずに、数字でもいいから Assertion Message 入れよう (そういえばひがさんはそうしてた)

Page 17: xUnit Test Patterns - Chapter16

Smells in This Chapter

● Assertion Roulette● Erratic Test● Fragile Test● Frequent Debugging● Manual Intervention● Slow Tests

Page 18: xUnit Test Patterns - Chapter16

Erratic Test

Page 19: xUnit Test Patterns - Chapter16

erratic【名】

1. 変人、奇人

2. 《地学》迷子石◆【同】erratic boulder

【形】

1. 〔人の言動が〕とっぴな、風変わりな、異常な、常軌を逸した

2. 一貫性のない、不安定な、一定しない、出来不出来がある、不規則な

3. 《地学》〔石などが氷河で〕漂移した

Page 20: xUnit Test Patterns - Chapter16

Erratic Test (1)

● 成功したり失敗したり、動きが一定でない● Symptoms

● いつ実行したかや誰が実行したかによってテストの結果が異なる

● 同じ Test Runner で実行しても結果がバラバラなことがある

Page 21: xUnit Test Patterns - Chapter16

Erratic Test (2)

● Impact● いつも Test Suite を緑にしたいので Erratic Test

を suite から外し、Lost Test (p268) につながる● Suite に入れたままにしたらしたで、他のテストで赤が出たときに気づかなかったりする

Page 22: xUnit Test Patterns - Chapter16

Erratic Test (3)

● Troubleshooting Advice● 原因がいろいろあるので手強い● 簡単に見つからない場合にはデータを定期的に採っ

て調べる必要がある– どこで成功し、どこで失敗したか– 全部のテストを実行したのか、一部を実行したのか– 同じ行を何度も実行した時に振る舞いが変わったか– 複数の Test Runner を同時に実行した時に振る舞いが変わったか

Page 23: xUnit Test Patterns - Chapter16

Erratic Test (4)

● Troubleshooting Advice● 原因がいろいろあるので手強い● 簡単に見つからない場合にはデータを定期的に採っ

て調べる必要がある– どこで成功し、どこで失敗したか– 全部のテストを実行したのか、一部を実行したのか– 同じ行を何度も実行した時に振る舞いが変わったか– 複数の Test Runner を同時に実行した時に振る舞いが変わったか

● データが採れたら次のページの切り分け図へ

Page 24: xUnit Test Patterns - Chapter16

Erratic Test (5)

Page 25: xUnit Test Patterns - Chapter16

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

Page 26: xUnit Test Patterns - Chapter16

Erratic Test Causes

● Erratic Test● Interacting Tests● Interacting Test Suites● Lonely Test● Resource Leakage● Resource Optimism● Unrepeatable Test● Test Run War● Nondeterministic Test

Page 27: xUnit Test Patterns - Chapter16

Interacting Tests (1)

● テストが他のテストに何らかの形で依存している

● バリエーション● Interacting Test Suite● Lonely Test

Page 28: xUnit Test Patterns - Chapter16

Interacting Tests (2)

● Symptoms● 独立して動かすときには成功しているテストが以下

の状況下で失敗する– 他のテストが suite に追加 / 削除されたとき– Suite の他のテストが失敗 / 成功したとき– テスト自身、もしくは他のテストのファイル名が変更さ

れたとき– Test Runner の新バージョンがインストールされたとき

Page 29: xUnit Test Patterns - Chapter16

Interacting Tests (3)

● Root Cause● 多くの場合、 Shared Fixture (p317) を使ってい

てかつ他のテストの (Shared Fixture への) 出力に依存しているために発生する

● 二つの側面から説明できる– The mechanism of interaction– The reason of interaction

Page 30: xUnit Test Patterns - Chapter16

Interacting Tests (4)

● The Mechanism of interaction● テスト (インスタンス) の寿命より長いものを使う

ときに起こる– データベース– static 変数

● やめておいたほうがいいもの– Singleton [GoF]– Registry [PofEAA]

Page 31: xUnit Test Patterns - Chapter16

Interacting Tests (5)

● The Reason of interaction● 他のテストの fixture setup phase で作られる

fixture に依存している● 他のテストが SUT に与える変化に依存している● 相互排他に行うべきテストを同時に行うことによる競合

Page 32: xUnit Test Patterns - Chapter16

Interacting Tests (5)

● 依存関係が終わるとき● 依存している他のテストが

– suite からいなくなる– SUT を変化させなくなる– SUT を変化させる際に失敗するようになる– 改名などにより、テスト実行の順番が後ろになる

● 競合が始まるとき● 競合しているテストが

– suite に加わる– 初めて成功した時点– テスト実行の順番が前になったとき

Page 33: xUnit Test Patterns - Chapter16

Interacting Tests (6)

● テスト対象自体は正しいのに失敗するようになるので、 “false-positive” になる。

● 一般論としてテスト実行順に依存するのは良くない● xUnit ファミリーは実行順を保証しない● TestNG は保証する

Page 34: xUnit Test Patterns - Chapter16

Interacting Tests (7)

● Possible Solution● Fresh Fixture (p311)

– もっとも望ましい● Shared Fixture を使いたい場合は

– Immutable Shared Fixture● 他のテストが作成するオブジェクトに依存している

時は– 両方のテストに Lazy Setup (p435) を書く

● コードが重複する場合は– Creation Method (p415)– Test Helper (p643)

Page 35: xUnit Test Patterns - Chapter16

Interacting Tests (8)

● Possible Solution (Cont'd)● テストで作成されたものが残っていることによる競

合には– Automated Fixture Teardown (p503)

● テストの依存を見つける方法● いつもと違う順番で実行してみる

– すべてのテストを逆順に実行してみる● 普段から常にバラバラの順番でテストを実行するよ

うにしておくと事故を防げて良い

Page 36: xUnit Test Patterns - Chapter16

Erratic Test Causes

● Erratic Test● Interacting Tests● Interacting Test Suites● Lonely Test● Resource Leakage● Resource Optimism● Unrepeatable Test● Test Run War● Nondeterministic Test

Page 37: xUnit Test Patterns - Chapter16

Interacting Test Suites (1)

● Symptoms● Suite 単体では成功するが、 Suite の Suite とい

う構成にすると失敗する

● Root Cause● よくあるのは、同じリソースを Suite が作成しよ

うとし、後から実行された Suite のほうが失敗するケース

Page 38: xUnit Test Patterns - Chapter16

Interacting Test Suites (2)

● 探すには● 失敗したテストを見る● それでも分からない時には

– 成功している方の Suite からテストを一つずつ取り除く● 失敗しなくなったときに取り除いたテストが依存元

● 場所はどこか– Shared Fixture– Test Method 内– Setup method– Test Utility

Page 39: xUnit Test Patterns - Chapter16

Interacting Test Suites (3)

● Root Cause (Cont'd)● 依存しあっているのは一つのテストとは限らない● テストケースではなく Suite Fixture Setup や

Setup Decorator が引き金となっているかもしれない

● NUnit についてまたいろいろ書いているが割愛

Page 40: xUnit Test Patterns - Chapter16

Interacting Test Suites (4)

● Possible Solution● 一番いいのは全部 Fresh Fixture にすること● Fresh Fixture にするのが難しければ Immutable

Shared Fixture● データベースに残っている残骸が問題なら

Automated Teardown

Page 41: xUnit Test Patterns - Chapter16

Erratic Test Causes

● Erratic Test● Interacting Tests● Interacting Test Suites● Lonely Test● Resource Leakage● Resource Optimism● Unrepeatable Test● Test Run War● Nondeterministic Test

Page 42: xUnit Test Patterns - Chapter16

Lonely Test (1)

● Interacting Tests の特殊例● Suite の一部としては実行成功するが、単独で

は動かない● 他のテストの触った Shared Fixture に依存してい

る– Chained Tests– Suite-level fixture setup

Page 43: xUnit Test Patterns - Chapter16

Erratic Test Causes

● Erratic Test● Interacting Tests● Interacting Test Suites● Lonely Test● Resource Leakage● Resource Optimism● Unrepeatable Test● Test Run War● Nondeterministic Test

Page 44: xUnit Test Patterns - Chapter16

Resource Leakage (1)

● Symptoms● テストがだんだん遅くなり、ついには失敗しだすように

なる● Test Runner / SUT / Database Sandbox(p650) をク

リーンアップするとテストが通るようになる● Root Cause

● 有限リソースをテストが消費し、それの開放に失敗している

● テストがどんどん遅くなる● テストを連続して続けるとリソースが使い尽くされ、後続のテストが失敗し始める

Page 45: xUnit Test Patterns - Chapter16

Resource Leakage (2)

● Root Cause (Cont'd)● SUT がリソースの開放に失敗している

– これが判明したら、直すのも難しくない● テストが fixture setup でリソースを消費し、開放に失敗している

Page 46: xUnit Test Patterns - Chapter16

Resource Leakage (3)

● Possible Solution● SUT がリソースを開放していないとき

– テストは仕事をきちんとしているので SUT のバグを直すべし

● テスト失敗時にリソース開放に失敗している場合 – Guaranteed In-line Teardown (p509)– Automated Teardown

● リソースプールのサイズを 1 にするのがいい● 問題がある場合にはテストがすぐ失敗するようにな

り、気づきやすい

Page 47: xUnit Test Patterns - Chapter16

Erratic Test Causes

● Erratic Test● Interacting Tests● Interacting Test Suites● Lonely Test● Resource Leakage● Resource Optimism● Unrepeatable Test● Test Run War● Nondeterministic Test

Page 48: xUnit Test Patterns - Chapter16

Resource Optimism

● Symptoms● ある環境下で動くテストが他の環境下で失敗する

● Root Cause● ある環境に存在するリソースが他の環境で不在

● Possible Solution● 可能なら、 Fresh Fixture をテストから毎回作成す

るようにする– 相対パスを使ってファイルを生成するなど

● 外部リソースを使わなければならない場合には SCM に入れることも視野に入れる

Page 49: xUnit Test Patterns - Chapter16

Erratic Test Causes

● Erratic Test● Interacting Tests● Interacting Test Suites● Lonely Test● Resource Leakage● Resource Optimism● Unrepeatable Test● Test Run War● Nondeterministic Test

Page 50: xUnit Test Patterns - Chapter16

Unrepeatable Test (1)

● Symptoms● あるテストがテスト群の先頭にある場合はテストが成功し、後続にある場合は失敗する。もしくはその逆。– Pass-Fail-Fail– Fail-Pass-Pass

Page 51: xUnit Test Patterns - Chapter16

Unrepeatable Test (2)

● Root Cause● (意図の有無に関わらず) Shared Fixture の使用

– Prebuilt Fixture を使っている場合にはDatabase ● Sandbox を使っていても、同一の開発者が同一の

テストランナーを使ったときは発生する● Lazy Setup を使っている場合には、 fixture が

class 変数を使いつづけたりする

Page 52: xUnit Test Patterns - Chapter16

Unrepeatable Test (3)

● Possible Solution● Fresh Fixture!

– Database Sandbox すら生ぬるい● Fake Database (p551)● 共有 Database を使わなければならない場合には

Distinct Generated Values (p723)● Automated Teardown

Page 53: xUnit Test Patterns - Chapter16

Erratic Test Causes

● Erratic Test● Interacting Tests● Interacting Test Suites● Lonely Test● Resource Leakage● Resource Optimism● Unrepeatable Test● Test Run War● Nondeterministic Test

Page 54: xUnit Test Patterns - Chapter16

Test Run War (1)

● Symptoms● 一人でテストを実行する時はテストが成功するが、

複数人が同時にテストを実行すると失敗する● Impact

● カットオフ間近に発生しがちだからイライラする!● 「テストが落ちたら最後の変更を疑え」ルールが機

能しなくなる

Page 55: xUnit Test Patterns - Chapter16

Test Run War (2)

● Root Cause● Shared Fixture (Database)

– 行の UPDATE / DELETE / SELECT などの競合– 悲観ロック

● Shared Fixture (File)– 既に他の人がファイルを開いているなど

Page 56: xUnit Test Patterns - Chapter16

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 の根本解決にはならないが、確率が減る

Page 57: xUnit Test Patterns - Chapter16

Erratic Test Causes

● Erratic Test● Interacting Tests● Interacting Test Suites● Lonely Test● Resource Leakage● Resource Optimism● Unrepeatable Test● Test Run War● Nondeterministic Test

Page 58: xUnit Test Patterns - Chapter16

Nondeterministic Test (1)

● Symptoms● テストがランダムに失敗する

– 人や環境、同時実行にも関係なさそう● 複数の Nondeterministic Test が suite にあると問題判別が難しい

● Impact● デバッグに時間がかかりすぎるし、イライラする

Page 59: xUnit Test Patterns - Chapter16

Nondeterministic Test (2)

● Root Cause● テスト毎に異なる値を使うことによって発生する

– ただし、異なる値を使うこと自体は悪いことではない。(例 : Distinct Generated Value)

– テスト対象アルゴリズムへの入力にランダムな値を使うときに問題が発生する

● Integer の負数や臨界値など● 長さ限界の文字列など

● ランダム値を使うことは悪くないように思えるが、カバレッジへの信頼とテストの repeatabilty が下がる

Page 60: xUnit Test Patterns - Chapter16

Nondeterministic Test (3)

● Root Cause (Cont'd)● Conditional Test Logic の使用がテストにランダ

ムさをもたらす– テスト毎にテスト実行パスが異なる

Page 61: xUnit Test Patterns - Chapter16

Nondeterministic Test (4)

● Possible Solution● Conditional Test Logic を取り除いて Linear に実

行されるようにする● ランダム値の使用を止めて deterministic な値を

使うようにする● 臨界値や同値分割を使う● テストが重複し始めたら

– Parameterized Test (p607)– Data-Driven Test (p288)

Page 62: xUnit Test Patterns - Chapter16

Smells in This Chapter

● Assertion Roulette● Erratic Test● Fragile Test● Frequent Debugging● Manual Intervention● Slow Tests

Page 63: xUnit Test Patterns - Chapter16

Fragile Test

Page 64: xUnit Test Patterns - Chapter16

fragile

【形】

1. 壊れやすい、もろい、割れやすい、脆弱な、傷(が)付きやすい、駄目になりやすい、危うい、軽い、か弱い、はかない、きゃしゃな

2. 実質のない、不十分な

3. 束の間の、逼迫した

4. 虚弱な、元気がない、調子が悪い

Page 65: xUnit Test Patterns - Chapter16

Fragile Test (1)

● Symptoms● 全然関係ないと思っていた部分の修正で、テストが

コンパイル/実行に失敗し始める– ときには production code に手を触れていないのに失敗

し始めることも● テスト自動化に頑張っていればいるほど、”four

sensitivities” (4 つの過敏症) に引っかかりやすくなる

Page 66: xUnit Test Patterns - Chapter16

Fragile Test (2)

● Impact● 変更を行う際にあちこちのテストを見なければなら

ないため、テストのメンテナンスコストが上がる● Incremental delivery を行う XP のようなプロセ

スでは、テストのメンテナンスコスト増は致命傷になりうる

Page 67: xUnit Test Patterns - Chapter16

Fragile Test (3)

● Troubleshooting Advice● 「落ちたテストに共通点は無いか?」と自問しよう

– テストと SUT の結合点が見えてくる

● 4 sensitivities● Interface Sensitivity

– コンパイルに失敗する– 動的型付け言語では型非互換ランタイムエラー

● Behavior Sensitivity– 直前の変更を戻したらテストが通るようになる

Page 68: xUnit Test Patterns - Chapter16

Fragile Test (4)

● Troubleshooting Advice (Cont'd)● Data Sensitivity

– 直前のコード変更を戻してもテストが失敗する● Shared Fixture を使っている or Fixture setup code を変更し

● Context Sensitivity– 直前のコード変更を戻してもテストが失敗する

● テストコードもテストデータもいじってない

Page 69: xUnit Test Patterns - Chapter16

Fragile Test (5)

● Troubleshooting Advice (Cont'd)● Data Sensitivity

– 直前のコード変更を戻してもテストが失敗する● Shared Fixture を使っている or Fixture setup code を変更し

● Context Sensitivity– 直前のコード変更を戻してもテストが失敗する

● テストコードもテストデータもいじってない

Page 70: xUnit Test Patterns - Chapter16

Fragile Test (6)

Page 71: xUnit Test Patterns - Chapter16

Fragile Test (7)

● Causes● Indirect Testing

– SUT に他のオブジェクトを介してアクセスしている● Eager Tests

– テストで検証をしすぎている● SUT の結合度が強すぎることの現れ

– そもそも小さい単位でテストするのが難しい SUT なのかもしれない (Hard-to-Test Code)

– Test Doubles を使い慣れていないだけかもしれない

Page 72: xUnit Test Patterns - Chapter16

Fragile Test Causes

● Fragile Test● Interface Sensitivity● Behavior Sensitivity● Data Sensitivity● Context Sensitivity● Overspecified Software● Sensitive Equality● Fragile Fixture

Page 73: xUnit Test Patterns - Chapter16

Interface Sensitivity

● Symptoms● SUT が変更されるとテストのコンパイル/実行に失

敗する– 静的型付け言語の場合はテストコンパイル失敗– 動的型付け言語の場合はテスト実行失敗– (変種) GUI 経由で Recorded Test を行っている場合

は、 UI 変更でテスト実行に失敗するとか

Page 74: xUnit Test Patterns - Chapter16

Interface Sensitivity (2)

● Possible Solution● 原因はわかりやすいことが多い

– コンパイル/テスト失敗する場所が問題箇所– 結局変更点が引き金になっていることが多い

● 内部で使われる interface の場合には SUT API Encapsulation– テスト用の Higher-Level Language (p41) を組む

● Test Utility Methods● Creation Methods

● “公布済み interface” の場合にはきちんと管理するしかない

Page 75: xUnit Test Patterns - Chapter16

Fragile Test Causes

● Fragile Test● Interface Sensitivity● Behavior Sensitivity● Data Sensitivity● Context Sensitivity● Overspecified Software● Sensitive Equality● Fragile Fixture

Page 76: xUnit Test Patterns - Chapter16

Behavior Sensitivity

● Symptoms● SUT が変更されると関係ない部分のテストの実行に失

敗する● Root Cause

● テストが失敗する事自体は悪くない。自動テストはそのためにある。

● Behavior Sensitivity になるのは、関係ないと思っていたテストの以下の部分が失敗するとき– Pre-test state setup (fixture setup)– Post-test state verification– Tear down (fixture teardown)

Page 77: xUnit Test Patterns - Chapter16

Behavior Sensitivity (2)

● Possible Solution● Fixture setup に失敗しているとき

– Creation Method● State Verification に失敗しているとき

– Custom Assertion– Verification Method

● (fixture teardown が無いが…たぶん)– Test Utility Method– Delegated Teardown

Page 78: xUnit Test Patterns - Chapter16

Fragile Test Causes

● Fragile Test● Interface Sensitivity● Behavior Sensitivity● Data Sensitivity● Context Sensitivity● Overspecified Software● Sensitive Equality● Fragile Fixture

Page 79: xUnit Test Patterns - Chapter16

Data Sensitivity

● Symptoms● テストデータが変更されるとテストの実行に失敗す

る– 既存テストデータの追加、更新、削除– Standard Fixture のセットアップコードが変更された– テスト実行前に Shared Fixture が変更されている

● Root Cause● データが変わっている!

– 検索に余計に引っかかるとか– 無くなっているとか

Page 80: xUnit Test Patterns - Chapter16

Data Sensitivity (2)

● Possible Solution● 多くの場合 result verification で発生する

– Verification logic を見直す● 一番良いのは Fresh Fixture● Database Partitioning Scheme● Delta Assertions

Page 81: xUnit Test Patterns - Chapter16

Fragile Test Causes

● Fragile Test● Interface Sensitivity● Behavior Sensitivity● Data Sensitivity● Context Sensitivity● Overspecified Software● Sensitive Equality● Fragile Fixture

Page 82: xUnit Test Patterns - Chapter16

Context Sensitivity

● Symptoms● 成功していたテストが突然失敗し始める

– Erratic Test との違いは、再現性があること

● Root Cause● 時刻や日付に依存している● SUT が他システムや OS に依存している● 本当にユニットテストになっているか確認しよう。テス

ト範囲が広すぎて Context Sensitivity に陥っていないか

● 広すぎると誰かが DOC を変更しただけでもテストは失敗する

Page 83: xUnit Test Patterns - Chapter16

Context Sensitivity (2)

● Root Cause (Cont'd)● 時刻や日付に依存しているコードがあるか● 他システムからの入力に依存しているコードがある

か● 実は問題が発生したりしなかったりするようなら

Erratic Test の知識を生かすべし● Possible Solution

● Test Stub (p529) に置き換える● 時刻依存なら Virtual Clock [VCTP] に置き換える

– (Fowler の FakeClock もみてみよう)

Page 84: xUnit Test Patterns - Chapter16

Fragile Test Causes

● Fragile Test● Interface Sensitivity● Behavior Sensitivity● Data Sensitivity● Context Sensitivity● Overspecified Software● Sensitive Equality● Fragile Fixture

Page 85: xUnit Test Patterns - Chapter16

Overspecified Software

● テストが SUT がどう振る舞うべきかについて「過剰に」記述されている● Test Double を使った Behavior Verification でよ

く発生する● Mock Object の使いすぎ

● 原因は「What」ではなく「How」をテストで記述してしまっていること● 実装依存になりすぎている

● Use the Front Door First !! (p40)

Page 86: xUnit Test Patterns - Chapter16

Fragile Test Causes

● Fragile Test● Interface Sensitivity● Behavior Sensitivity● Data Sensitivity● Context Sensitivity● Overspecified Software● Sensitive Equality● Fragile Fixture

Page 87: xUnit Test Patterns - Chapter16

Sensitive Equality

● オブジェクトを文字列に変換して expected と actual を比較している● 関係ない部分の比較で失敗しやすい

● interface の semantics が変更されているという意味では Interface Sensitivity とも言える(?)

● オブジェクトの文字列変換による比較は災いの素 (Gerard)● まさーるさんは文字列比較を奨めていたが…

Page 88: xUnit Test Patterns - Chapter16

Fragile Test Causes

● Fragile Test● Interface Sensitivity● Behavior Sensitivity● Data Sensitivity● Context Sensitivity● Overspecified Software● Sensitive Equality● Fragile Fixture

Page 89: xUnit Test Patterns - Chapter16

Fragile Fixture

● 新しいテストのために Standard Fixture を編集したら、全然違うテストが失敗した● Data Sensitivity や Context Sensitivity の変種● Fixture の性質の違い

Page 90: xUnit Test Patterns - Chapter16

ご清聴ありがとう

ございました