32
Androidで使える モックフレームワーク Android Test Casual Talks #1 LT資料 2013.12.13 長谷川 孝二 @nowsprinting

Androidで使えるモックフレームワーク

Embed Size (px)

DESCRIPTION

Android Test Casual Talks #1 LT資料 http://www.zusaar.com/event/1917003

Citation preview

Page 1: Androidで使えるモックフレームワーク

Androidで使える モックフレームワーク

Android Test Casual Talks #1 LT資料

2013.12.13 長谷川 孝二 @nowsprinting

Page 2: Androidで使えるモックフレームワーク

自己紹介長谷川 孝二 @nowsprinting (twitter, github, etc...)

• テスト自動化研究会

• Androidテスト部

• iOS/Androidアプリ開発者

• 受託開発(フリーランス)

• 自社開発

Page 3: Androidで使えるモックフレームワーク

アジェンダ• モックとは • Dalvik上で動作するモックFWの変遷

• モックフレームワークの使用例 • EasyMock

• Mockito

Page 4: Androidで使えるモックフレームワーク

モックとは

Page 5: Androidで使えるモックフレームワーク

xUnit Test Patternsでの定義

#11 Using Test Doubles

#23 Test Double Patterns

Page 6: Androidで使えるモックフレームワーク

xUnit Test Patternsでの定義

• Test Double == 身代わり、影武者の意

• Test Stub(間接入力を操作する)

• Test Spy(間接出力を記録する)

• Mock Object(間接出力の検証もする)

• Fake Object(偽の間接入力を返す)

• Dummy Object(nullじゃない程度)

Page 7: Androidで使えるモックフレームワーク

テストの基本 SUTへの入力に対する 出力を検証する

Page 8: Androidで使えるモックフレームワーク

依存オブジェクトがあると難しくなる

Page 9: Androidで使えるモックフレームワーク

依存オブジェクト

• Aさん担当クラス(進捗どうですか? これバグじゃありませんか?)

• Date, Calendar, Random(再現性)

• HttpClient(例外、通信エラー、正常系でも再現性の確保)

Page 10: Androidで使えるモックフレームワーク

Test Stub/Fake Objectで 間接入力を固定化

Page 11: Androidで使えるモックフレームワーク

Test Spy/Mock Objectで 間接出力を検証する

Page 12: Androidで使えるモックフレームワーク

• xUnit Test Patterns(洋書) http://xunitpatterns.com/ http://www.fieldnotes.jp/xutp/ ( 読書会の記録)

• 井芹さんのエントリ xUnit Test PatternsのTest Doubleパターン(Mock,Stub,Fake,Dummy等の定義)

http://goyoki.hatenablog.com/entry/20120301/1330608789

詳しくは…

Page 13: Androidで使えるモックフレームワーク

モックフレームワークとは

• Test Double == 身代わり、影武者の意

• Test Stub(間接入力を操作する)

• Test Spy(間接出力を記録する)

• Mock Object(間接出力の検証もする)

• Fake Object(偽の間接入力を返す)

• Dummy Object(nullじゃない程度)

全部できる! しかも動的に

Page 14: Androidで使えるモックフレームワーク

Dalvik上で動く モックフレームワークの変遷

Page 15: Androidで使えるモックフレームワーク

Android Mock

• 2009年、Dalvikチームが4週間で作った

• EasyMockベース

• 設定めんどくさい • @IT記事

Android Mockを利用してHTTP通信をテストするには http://www.atmarkit.co.jp/ait/articles/1204/13/news144.html

Page 16: Androidで使えるモックフレームワーク

その半年後…

Page 17: Androidで使えるモックフレームワーク

Android Mock

• 2012年11月、開発・サポート終了

Page 18: Androidで使えるモックフレームワーク

• https://code.google.com/p/mockito/

• MIT License

• 1.9.5rc-1(03-06-2012)でDalvikサポート

(動作にはdexmakerが必要)

• Strict Mockは無く、間接出力の厳密な 検証はInOrderを使って行なう

Page 19: Androidで使えるモックフレームワーク

• http://easymock.org/

• Apache License 2.0

• 3.2(2013-07-11)でDalvikサポート

(動作にはdexmakerが必要)

• Nice Mock, Mock, Strict Mockの三種類で 検証の厳密さが異なる

Page 20: Androidで使えるモックフレームワーク

モックフレームワークの使用例 EasyMock編

Page 21: Androidで使えるモックフレームワーク

EasyMockの設定• easymock-3.2.jarを入手、libs/に格納

http://easymock.org/Downloads.html

• dexmaker-1.0.jarを入手、libs/に格納 http://code.google.com/p/dexmaker/

• Build Pathにeasymock-3.2.jarを追加

Page 22: Androidで使えるモックフレームワーク

モックの使用例 1/2// HTTPステータス500を返すStatusLineモックStatusLine mockStatusLine = EasyMock.createMock(StatusLine.class);EasyMock.expect(mockStatusLine.getStatusCode()) .andReturn(500);EasyMock.replay(mockStatusLine);!(snip)!// テスト対象のインスタンスフィールドにある// HttpClientをモックに差し替えるmFxRateLoader.mHttpclient = mockHttpClient;

Page 23: Androidで使えるモックフレームワーク

モックの使用例 2/2// テスト実行try { mFxRateLoader.requestFeed(); fail();!} catch (InvalidHttpStatusCodeException e) { // 例外がスローされるのが正しい振る舞い // ステータスコードが正しいか検証 assertEquals(500, e.getStatusCode());}

Page 24: Androidで使えるモックフレームワーク

例外発生のテスト 1/2// 通信できない状態の例外をスローするHttpClientモックException expected = new UnknownHostException();HttpClient mockHttpClient = EasyMock.createMock(HttpClient.class);EasyMock.expect(mockHttpClient.execute((HttpUriRequest)EasyMock.notNull())).andThrow(expected);

EasyMock.replay(mockHttpClient);!// テスト対象のインスタンスフィールドにある// HttpClientをモックに差し替えるmFxRateLoader.mHttpclient = mockHttpClient;

Page 25: Androidで使えるモックフレームワーク

例外発生のテスト 2/2

// テスト実行try { mFxRateLoader.requestFeed(); fail("UnknownHostExceptionがthrowされていない");!} catch (UnknownHostException e) {

// 例外がスローされるのが正しい振る舞い}

Page 26: Androidで使えるモックフレームワーク

StrictMockの例 1/2// ダミーのパース結果を返すXmlPullParserモックXmlPullParser mockParser = EasyMock.createStrictMock(XmlPullParser.class);mockParser.setInput((InputStream)EasyMock.notNull(), (String)EasyMock.notNull());EasyMock.expect(mockParser.getEventType()).andReturn(XmlPullParser.START_TAG);EasyMock.expect(mockParser.getName()).andReturn("gesmes:Envelope");// 無視されるEasyMock.expect(mockParser.next()).andReturn(XmlPullParser.START_TAG);(snip)EasyMock.expect(mockParser.getName()).andReturn("Cube");// USDEasyMock.expect(mockParser.getAttributeValue(null, "currency")).andReturn("USD");EasyMock.expect(mockParser.getAttributeValue(null, "rate")).andReturn(SEED_EURUSD);EasyMock.expect(mockParser.next()).andReturn(XmlPullParser.START_TAG);(snip)EasyMock.expect(mockParser.next()).andReturn(XmlPullParser.END_TAG); // </gesmes:Envelope>EasyMock.expect(mockParser.next()).andReturn(XmlPullParser.END_DOCUMENT);EasyMock.replay(mockParser);!// テスト対象のインスタンスフィールドにあるHttpClientをモックに差し替えるmFxRateLoader.mParser = mockParser;

Page 27: Androidで使えるモックフレームワーク

StrictMockの例 2/2

// テスト実行InputStream dummyResponseBody = createDummyInputStream();FxRate actual = mFxRateLoader.parseFeed(dummyResponseBody);assertEquals("EUR/USDは正しくパースされている", expectedEurusd, actual.eurusd);assertEquals("EUR/JPYは正しくパースされている", expectedEurjpy, actual.eurjpy);

Page 28: Androidで使えるモックフレームワーク

StrictMockの例 2/2

// テスト実行InputStream dummyResponseBody = createDummyInputStream();FxRate actual = mFxRateLoader.parseFeed(dummyResponseBody);assertEquals("EUR/USDは正しくパースされている", expectedEurusd, actual.eurusd);assertEquals("EUR/JPYは正しくパースされている", expectedEurjpy, actual.eurjpy);

parseFeed()内でStrictMockに定義した順にメソッドを呼ばれていないと、その場で例外発生

Page 29: Androidで使えるモックフレームワーク

Mockの乱用は危険• 実装のテストになりがち →何をテストしているのか?

• 実装の変更に弱い →壊れやすいテスト(Fragile Test)

→保守の放棄

Page 30: Androidで使えるモックフレームワーク

モックフレームワークの使用例 Mockito編

Page 31: Androidで使えるモックフレームワーク

買って 買って 買って 買って

買って 買って 買って 買って

買って 買って 買って 買って

買って 買って 買って 買って

買って 買って 買って 買って

買って 買って 買って 買って

Page 32: Androidで使えるモックフレームワーク

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