Contenu connexe
Similaire à Unit test in android (20)
Unit test in android
- 7. public static String fizzbuzz(int value) {
String message;
if (value % 15 == 0) {
message = "FizzBuzz";
} else if (value % 5 == 0) {
message = "Buzz";
} else if (value % 3 == 0) {
message = "Fizz";
} else {
message = String.valueOf(value);
}
return message;
}
FizzBuzz
- 16. @Test
@Config(shadows = { MyShadowTextView.class })
public void getTextShouldReturnHelloRobolectric() {
// SetUp
Context context =
Robolectric.application.getApplicationContext();
TextView textView = new TextView(context);
// Exercise
CharSequence actualText = textView.getText();
// Verify
assertEquals(actualText, "Hello, Robolectric!");
}
Shadowの利用例
- 23. // 実行結果
int actualValue = 10 / 2;
!
// 期待結果
int expectedValue = 5;
!
// "10 / 2"が"5"と等しくなることを表明
assertEquals(actualValue, expectedValue);
アサーションの例
- 26. // Exercise
List<String> devices = new ArrayList<String>();
devices.add("Nexus 5");
devices.add("Nexus 7");
!
!
// Verify
assertNotNull(devices);
assertEquals(2, devices.size());
assertTrue(devices.contains("Nexus 5"));
JUnit
- 27. // Exercise
List<String> devices = new ArrayList<String>();
devices.add("Nexus 5");
devices.add("Nexus 7");
!
!
// Verify
assertThat(devices, is(notNullValue()));
assertThat(devices.size(), is(equalTo(2)));
assertThat(devices, hasItem("Nexus 5"));
Hamcrest
- 28. // Exercise
List<String> devices = new ArrayList<String>();
devices.add("Nexus 5");
devices.add("Nexus 7");
!
!
// Verify
assertThat(devices)
.isNotNull()
.hasSize(2)
.contains("Nexus 5");
FEST
- 30. // テストコード
List<String> devices = new ArrayList<String>();
devices.add("Nexus 5");
devices.add("Nexus 7");
assertTrue(devices.contains("Nexus 4"));
!
!
// エラーメッセージ
java.lang.AssertionError
!
!
!
!
JUnit
- 31. // テストコード
List<String> devices = new ArrayList<String>();
devices.add("Nexus 5");
devices.add("Nexus 7");
assertThat(devices, hasItem("Nexus 4"));
!
!
// エラーメッセージ
java.lang.AssertionError:
Expected: a collection containing "Nexus 4"
but: was "Nexus 5", was "Nexus 7”
!
!
Hamcrest
- 32. // テストコード
List<String> devices = new ArrayList<String>();
devices.add("Nexus 5");
devices.add("Nexus 7");
assertThat(devices).contains("Nexus 4");
!
!
// エラーメッセージ
java.lang.AssertionError: expecting:
<['Nexus 5', 'Nexus 7']>
to contain:
<['Neuxus 4']>
but could not find:
<['Neuxus 4']>
FEST
- 34. // テストコード
TextView textView = (TextView) activity
.findViewById(R.id.text_view);
assertThat(textView.getText())
.isEqualTo(activity.getString(R.string.message));
assertThat(textView.getVisibility())
.isEqualTo(View.VISIBLE);
!
!
// エラーメッセージ
org.junit.ComparisonFailure: expected:
<[0]>
but was:
<[8]>
FEST
- 35. // テストコード
TextView textView = (TextView) activity
.findViewById(R.id.text_view);
assertThat(textView)
.hasText(R.string.message)
.isVisible();
!
!
!
// エラーメッセージ
java.lang.AssertionError:
Expected to be visible but was gone
!
FEST Android
- 39. class MockInputStream extends InputStream {
!
private boolean mIsRead;
private boolean mIsClosed;
!
@Override
public int read() throws IOException {
mIsRead = true;
return 0;
}
!
public boolean isRead() {
return mIsRead;
}
!
@Override
public void close() throws IOException {
mIsClosed = true;
}
!
public boolean isClosed() {
return mIsClosed;
}
!
}
モックオブジェクトの例
- 42. 振る舞いの変更
// モックオブジェクトの作成
InputStream mocked = mock(InputStream.class);
!
// 戻り値の変更
when(mocked.read()).thenReturn(-1);
!
// 例外の送出
when(mocked.read()).thenThrow(new IOException());
!
// ロジックの変更
when(mocked.read()).thenAnswer(new Answer<Integer>() {
!
@Override
public Integer answer(InvocationOnMock invocation)
throws Throwable {
int length;
...
return length;
}
});
- 43. フィールドの変更
// 内部にInputStreamを保持するクラス
MyObject object = new MyObject();
// フィールドの取得
InputStream stream = (InputStream) Whitebox
.getInternalState(object, “mStream");
!
// スパイオブジェクトの作成
Socket spied = spy(stream);
!
// フィールドの変更
Whitebox
.setInternalState(object, "mStream", spied);
- 54. List<String> list = new MyList<String>();
list.add("Android");
// 別のメソッドで検証
assertThat(list).hasSize(1);
サンプル
- 56. InputStream mocked = mock(InputStream.class);
IoUtils.close(mocked);
!
// closeメソッドの呼び出し検証
verify(mocked).close();
サンプル
- 60. // privateメソッドなので呼び出せない
private String buildMessage() {
String message;
// do something
return message;
}
!
// package privateに変更
String buildMessage() {
String message;
// do something
return message;
}
サンプル
- 63. // timeoutを指定
@Test(timeout = 1000)
public void test() throws InterruptedException{
CountDownLatch latch = new CountDownLatch(1);
AsyncProcess.execute(new Callback() {
@Override
public void onComplete() {
// 処理完了時にcountDownを呼出
latch.countDown();
}
});
!
// 処理完了まで待機
latch.await();
!
...
}
サンプル
- 66. // 常に同じレスポンスを返却
FakeHttpLayer layer = Robolectric.getFakeHttpLayer();
layer.setDefaultHttpResponse(200, "Hello, World!");
!
!
// 順番にレスポンスを変更
FakeHttpLayer layer = Robolectric.getFakeHttpLayer();
layer.addPendingHttpResponse(200, "Hello, Nexus 4!");
layer.addPendingHttpResponse(200, "Hello, Nexus 5!");
layer.addPendingHttpResponse(200, "Hello, Nexus 7!");
!
!
// 動的にレスポンスを変更
FakeHttpLayer layer = Robolectric.getFakeHttpLayer();
layer.addHttpResponseRule(new MyResponseRule());
サンプル
- 68. class StubURLStreamHandler extends URLStreamHandler {
@Override
protected URLConnection openConnection(URL url)
throws IOException {
// HttpURLConnectionを作成
return new StuHttpURLConnection(url);
}
}
!
class StubURLStreamHandlerFactory implements
URLStreamHandlerFactory {
@Override
public URLStreamHandler createURLStreamHandler(
String protocol) {
// URLStreamHandlerを作成
return new StubURLStreamHandler();
}
}
!
// URLStreamHandlerFactoryを設定
URL.setURLStreamHandlerFactory(
new StubURLStreamHandlerFactory());
サンプル
- 71. // DatabaseMapのinterfaceを実装
class MemoryDatabaseMap implements DatabaseMap {
!
@Override
public String getDriverClassName() {
return JDBC.class.getName();
}
!
@Override
public String getConnectionString(File file) {
// インメモリデータベースを使うように指定
return "jdbc:sqlite::memory:";
}
!
@Override
public String getMemoryConnectionString() {
// インメモリデータベースを使うように指定
return "jdbc:sqlite::memory:";
}
!
@Override
public int getResultSetType() {
return ResultSet.TYPE_FORWARD_ONLY;
}
!
@Override
public String getSelectLastInsertIdentity() {
return "SELECT last_insert_rowid() AS id";
}
!
}
サンプル
- 75. // ActivityControllerを生成
ActivityController<MainActivity> controller =
Robolectric.buildActivity(MainActivity.class);
!
// Activityの生成
controller.create().start().resume().visible();
!
// Activityの取得
MainActivity activity = controller.get();
// Activityの操作
TextView textView = (TextView) activity
.findViewById(R.id.text_view);
...
!
// Activityの破棄
controller.pause().stop().destroy();
サンプル
- 78. private MyService mService;
!
@Before
public void setUp() {
// Serviceを生成
mService = new MyService();
mService.onCreate();
}
@Test
public void test() {
// Serviceを実行
Intent intent = new Intent(Intent.ACTION_SEARCH);
intent.putExtra(SearchManager.QUERY, "Hello, World!");
mService.onStartCommand(intent, 0, 0);
}
!
@After
public void tearDown() {
// Serviceを破棄
mService.onDestroy();
}
サンプル
- 81. // ShadowAppWidgetManagerの生成
Context context = Robolectric.application
.getApplicationContext();
AppWidgetManager manager =
AppWidgetManager.getInstance(context);
ShadowAppWidgetManager shadowManager =
Robolectric.shadowOf(manager);
// Widgetの生成
int widgetId = shadowManager.createWidget(
MyWidgetProvider.class,
R.layout.activity_main);
// Viewの取得
View widgetView = shadowManager.getViewFor(widgetId);
!
...
サンプル
- 84. // ShadowContentResolverの生成
ContentResolver resolver =
Robolectric.application.getContentResolver();
ShadowContentResolver shadowResolver =
Robolectric.shadowOf(resolver);
!
// ContentProviderの登録
shadowResolver.registerProvider(
“com.example.android.unittest”
new MyContentProvider());
...
// INSERTステートメントの取得
List<InsertStatement> insertStatements =
shadowResolver.getInsertStatements();
// UPDATEステートメントの取得
List<UpdateStatement> updateStatements =
shadowResolver.getUpdateStatements();
// DELETEステートメントの取得
List<DeleteStatement> deleteStatements =
shadowResolver.getDeleteStatements();
// notifyChangeで通知されたURIの取得
List<NotifiedUri> notifiedUris =
shadowResolver.getNotifiedUris();
サンプル
- 87. // 事前処理
ShadowApplication shadowApplication =
Robolectric.getShadowApplication();
Context context =
Robolectric.application.getApplicationContext();
// 登録済みBroadcastReceiverの取得
List<Wrapper> registered =
shadowApplication.getRegisteredReceivers();
// Intentに該当するBroadcastReceiverの取得
Intent intent = new Intent("MY_ACTION");
List<BroadcastReceiver> receivers =
shadowApplication.getReceiversForIntent(intent);
// Intentを擬似的に受信
BroadcastReceiver receiver = receivers.get(0);
receiver.onReceive(context, intent);
サンプル