xunit test patterns - chapter11

19
Chapter 11. Using Test Doubles

Upload: takuto-wada

Post on 05-Dec-2014

3.660 views

Category:

Technology


4 download

DESCRIPTION

handout for xUnit Test Patterns Reading Groups Japan

TRANSCRIPT

Page 1: xUnit Test Patterns - Chapter11

Chapter 11.Using Test Doubles

Page 2: xUnit Test Patterns - Chapter11

前回のまとめ

Page 3: xUnit Test Patterns - Chapter11

前回のまとめ設定可能?

Dummy コンパイラを満足させるためだけに存在 ×

Stub テストから設定された値を SUT に返すために使う。 ○

Spy SUT から値を受けとるために使う。SUT とのやりとりを覚えていて、テストは後で spy から聞き出す。

Mock 間接的入力/出力に使え、SUT とのやりとりを厳格にも寛容にもすることができる。予想外のやりとりならすぐ失敗させることもできる

Fake テスト用に単純化された、 DOC の別実装。実際には DB に接続に行かず、特定の値を返す Dao とか。

×

Page 4: xUnit Test Patterns - Chapter11

Providing the Test Double

● 2 approaches● Hand-Built Test Double

– Hard-Coded Test Double– ちょっとがんばれば configurable になる

● Dynamically Generated Test Double– 基本的に Configurable Test Double– jMock ファミリーが代表的 (←ちょっと情報が古い)– EasyMock は少し毛色が違う

Page 5: xUnit Test Patterns - Chapter11

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

      

Page 6: xUnit Test Patterns - Chapter11

Pseudo-Objects

● 静的型付け言語で Hand-Coded な Double を作成するときには、 Pseudo-Object を作成しておくと楽になる● Inner Test Doubles や Self-Shunt につかう

Page 7: xUnit Test Patterns - Chapter11

/** * 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

Page 8: xUnit Test Patterns - Chapter11

Configuring the Test Double

● Test Stub, Mock Object は何を返すか、何を話しかけられるかの設定行為が必要● Hard-Coded Test Double の場合は設計時(コーディン

グ時)に設定を行う● Configurable Test Double はランタイムにテストから

設定される– Stub, Spy は何を返すかの設定が必要– Mock は何を話しかけられるかの設定も加えて必要

● どういう値を選ぶかは設計行為そのもの● テストの理解容易性● Double の再利用性

Page 9: xUnit Test Patterns - Chapter11

Configuring the Test Double(2)

● Fake は SUT から使われるだけなのでランタイムに設定される必要なし

● Dummy は実行されないので設定の必要なし● Procedual Test Stub は Hard-Coded の代表

例●

Page 10: xUnit Test Patterns - Chapter11

Configuring the Test Double(3)

● Configurable Test Double の設定方法● Configuration Interface● Configuration Mode

● 利点● テスト間での再利用性が高い● 値がテストコード内に書かれるので理解しやすい

– Mystery Guest アンチパターンを防ぐ

● 設定場所は fixture setup と同じ扱い

Page 11: xUnit Test Patterns - Chapter11

Installing the Test Double

● “install” という言葉● 基本的な流れ

● Test Double のインスタンス化● Configurable Test Double な場合は設定する● 「 Test Double を使え」とSUT の実行前か実行時

に伝える● “install” 方法は何種類かある

● 種類の選択はテスト容易性の設計といえる● 選択の余地が無い場合も多いが、再設計もあるよ!

Page 12: xUnit Test Patterns - Chapter11

Installing the Test Double(2)

● 基本的な選択肢は三つ● Dependency Injection● Dependency Lookup● Test Hook

● IoC フレームワークが提供されている言語の場合にはいろいろ仕組みを自分で作らずに済む

Page 13: xUnit Test Patterns - Chapter11

Dependency Injection

● SUT が依存を自ら探すのではなく、誰かがランタイムに外から設定する

● 偽者を渡しやすいので TDD との相性◎● 依存性解決に関する知識が SUT から無くなる

ので SUT の再利用性も大幅 UP● 3 types

● Setter Injection● Constructor Injection● Parameter Injection

Page 14: xUnit Test Patterns - Chapter11

Dependency Lookup

● テスト容易性を設計に組み込んでいなかったり、Dependency Injection の仕組みが言語に無い場合に使う

● SUT が誰かに DOC の作成を依頼する● DOC の生成知識自体は SUT は持たない● 「誰か」は有名人になってしまう

● 2 types (あまり違いは無い)● Object Factory (GoF)● Service Locator (PofEAA)

Page 15: xUnit Test Patterns - Chapter11

Test Specific Subclass

Page 16: xUnit Test Patterns - Chapter11

Test-Specific Subclass

● DI も DL も無くても、まだ諦めてはいけない● 介入可能な仕組みを組み上げてもがこう

● Singleton 死すべし● DI 可能な仕組みを備えた、SUT のサブクラスを

作成する● テストに必要な部分に関して、 SUT のオーバーライ

ドを行う● でも SUT が non-private な self-call をする必要が

ある

Page 17: xUnit Test Patterns - Chapter11

Test-Specific Subclass(2)

● DOC のサブクラスを作成する手もある● Subclassed Test Double になる● SUT のサブクラス作成よりは相対的に安全

Page 18: xUnit Test Patterns - Chapter11

Other Ways (最後の手段)

● Test Hooks● Test Logic in Production● レガシーコードからの第一手として

● さらなる手段は WEwLC にたくさんあるよ!● Object Seam とか● Dependency Breaking Technique の宝庫

– でも使わない状況になるのが一番幸せ

● AOP もある

Page 19: xUnit Test Patterns - Chapter11

ご清聴ありがとうございました