xunit test patterns - chapter11
Post on 05-Dec-2014
3.660 Views
Preview:
DESCRIPTION
TRANSCRIPT
Chapter 11.Using Test Doubles
前回のまとめ
前回のまとめ設定可能?
Dummy コンパイラを満足させるためだけに存在 ×
Stub テストから設定された値を SUT に返すために使う。 ○
Spy SUT から値を受けとるために使う。SUT とのやりとりを覚えていて、テストは後で spy から聞き出す。
○
Mock 間接的入力/出力に使え、SUT とのやりとりを厳格にも寛容にもすることができる。予想外のやりとりならすぐ失敗させることもできる
○
Fake テスト用に単純化された、 DOC の別実装。実際には DB に接続に行かず、特定の値を返す Dao とか。
×
Providing the Test Double
● 2 approaches● Hand-Built Test Double
– Hard-Coded Test Double– ちょっとがんばれば configurable になる
● Dynamically Generated Test Double– 基本的に Configurable Test Double– jMock ファミリーが代表的 (←ちょっと情報が古い)– EasyMock は少し毛色が違う
public void testDisplayCurrentTime_AtMidnight_PS() throws Exception { //Define and instantiate Test Stub TimeProvider testStub = new PseudoTimeProvider() { //Anonymous inner stub public Calendar getTime(String timeZone) { Calendar myTime = new GregorianCalendar(); myTime.set(Calendar.MINUTE, 0); myTime.set(Calendar.HOUR_OF_DAY, 0); return myTime; } }; //Instantiate SUT TimeDisplay sut = new TimeDisplay(); //Inject Test Stub into SUT sut.setTimeProvider(testStub); //Exercise SUT String result = sut.getCurrentTimeAsHtmlFragment(); //Verify direct output String expectedTimeString = "<span class=\"tinyBoldText\">Midnight</span>"; assertEquals("Midnight", expectedTimeString, result); }
Pseudo-Objects
● 静的型付け言語で Hand-Coded な Double を作成するときには、 Pseudo-Object を作成しておくと楽になる● Inner Test Doubles や Self-Shunt につかう
/** * Base class for hand-coded Test Stubs and Mock Objects */ public class PseudoTimeProvider implements ComplexTimeProvider {
public Calendar getTime() throws TimeProviderEx { throw new PseudoClassException(); }
public Calendar getTimeDifference(Calendar baseTime, Calendar otherTime) throws TimeProviderEx { throw new PseudoClassException(); }
public Calendar getTime(String timeZone ) throws TimeProviderEx { throw new PseudoClassException(); } }
Pseudo-Objects
Configuring the Test Double
● Test Stub, Mock Object は何を返すか、何を話しかけられるかの設定行為が必要● Hard-Coded Test Double の場合は設計時(コーディン
グ時)に設定を行う● Configurable Test Double はランタイムにテストから
設定される– Stub, Spy は何を返すかの設定が必要– Mock は何を話しかけられるかの設定も加えて必要
● どういう値を選ぶかは設計行為そのもの● テストの理解容易性● Double の再利用性
Configuring the Test Double(2)
● Fake は SUT から使われるだけなのでランタイムに設定される必要なし
● Dummy は実行されないので設定の必要なし● Procedual Test Stub は Hard-Coded の代表
例●
Configuring the Test Double(3)
● Configurable Test Double の設定方法● Configuration Interface● Configuration Mode
● 利点● テスト間での再利用性が高い● 値がテストコード内に書かれるので理解しやすい
– Mystery Guest アンチパターンを防ぐ
● 設定場所は fixture setup と同じ扱い
Installing the Test Double
● “install” という言葉● 基本的な流れ
● Test Double のインスタンス化● Configurable Test Double な場合は設定する● 「 Test Double を使え」とSUT の実行前か実行時
に伝える● “install” 方法は何種類かある
● 種類の選択はテスト容易性の設計といえる● 選択の余地が無い場合も多いが、再設計もあるよ!
Installing the Test Double(2)
● 基本的な選択肢は三つ● Dependency Injection● Dependency Lookup● Test Hook
● IoC フレームワークが提供されている言語の場合にはいろいろ仕組みを自分で作らずに済む
Dependency Injection
● SUT が依存を自ら探すのではなく、誰かがランタイムに外から設定する
● 偽者を渡しやすいので TDD との相性◎● 依存性解決に関する知識が SUT から無くなる
ので SUT の再利用性も大幅 UP● 3 types
● Setter Injection● Constructor Injection● Parameter Injection
Dependency Lookup
● テスト容易性を設計に組み込んでいなかったり、Dependency Injection の仕組みが言語に無い場合に使う
● SUT が誰かに DOC の作成を依頼する● DOC の生成知識自体は SUT は持たない● 「誰か」は有名人になってしまう
● 2 types (あまり違いは無い)● Object Factory (GoF)● Service Locator (PofEAA)
Test Specific Subclass
Test-Specific Subclass
● DI も DL も無くても、まだ諦めてはいけない● 介入可能な仕組みを組み上げてもがこう
● Singleton 死すべし● DI 可能な仕組みを備えた、SUT のサブクラスを
作成する● テストに必要な部分に関して、 SUT のオーバーライ
ドを行う● でも SUT が non-private な self-call をする必要が
ある
Test-Specific Subclass(2)
● DOC のサブクラスを作成する手もある● Subclassed Test Double になる● SUT のサブクラス作成よりは相対的に安全
Other Ways (最後の手段)
● Test Hooks● Test Logic in Production● レガシーコードからの第一手として
● さらなる手段は WEwLC にたくさんあるよ!● Object Seam とか● Dependency Breaking Technique の宝庫
– でも使わない状況になるのが一番幸せ
● AOP もある
ご清聴ありがとうございました
top related