More Related Content
Similar to TDDの話と初めてのUIテスト
Similar to TDDの話と初めてのUIテスト (20)
More from ichirokato5 (6)
TDDの話と初めてのUIテスト
- 2. About Me
加藤一郎
Android歴:一年ちょっと
趣味:キャンプ、BBQ、旅行、社会人バスケ
所属:ヤフー株式会社
(ヤフオク! Androidエンジニア)
Copyright © 2019 Yahoo Japan Corporation. All Rights Reserved.
- 5. HOW TO DO TDD
失敗するテストを書く
実装する
テストが成功すること確認する
リファクタリング
Copyright © 2019 Yahoo Japan Corporation. All Rights Reserved.
- 11. カスタムMatcher
private fun withItemText(itemText: String): Matcher<View> {
checkArgument(itemText.isNotEmpty(), "itemText cannot be null or empty")
return object : TypeSafeMatcher<View>() {
public override fun matchesSafely(item: View): Boolean {
return allOf(
isDescendantOfA(isAssignableFrom(RecyclerView::class.java)),
withText(itemText)).matches(item)
}
override fun describeTo(description: Description) {
description.appendText("isDescendantOfA RV with text $itemText")
}
}
}
@Test
fun addNoteToNotesList() {
val newNoteTitle = "Espresso"
val newNoteDescription = "UI testing for Android"
onView(withId(fab_add_notes)).perform(click())
onView(withId(add_note_title)).perform(typeText(newNoteTitle), closeSoftKeyboard())
onView(withId(R.id.add_note_description)).perform(typeText(newNoteDescription), closeSoftKeyboard())
onView(withId(fab_add_notes)).perform(click())
val action = scrollTo<RecyclerView.ViewHolder>(hasDescendant(withText(newNoteDescription)))
onView(withId(notes_list)).perform(action)
onView(withItemText(newNoteDescription)).check(matches(isDisplayed()))
}
Copyright © 2019 Yahoo Japan Corporation. All Rights Reserved.
- 12. Activityの起動を遅らせる
@Rule @JvmField
var noteDetailActivityTestRule =
ActivityTestRule(NoteDetailActivity::class.java, true,
false)
@Before
fun intentWithStubbedNoteId() {
FakeNotesServiceApiImpl.addNotes(NOTE)
val startIntent = Intent()
startIntent.putExtra(NoteDetailActivity.EXTRA_NOTE_ID, NOTE.id)
noteDetailActivityTestRule.launchActivity(startIntent)
registerIdlingResource()
}
Copyright © 2019 Yahoo Japan Corporation. All Rights Reserved.
- 13. アイドリング状態になったらテ
スト開始
object EspressoIdlingResource {
private const val RESOURCE = "GLOBAL"
private val mCountingIdlingResource = SimpleCountingIdlingResource(RESOURCE)
val idlingResource: IdlingResource
get() = mCountingIdlingResource
fun increment() {
mCountingIdlingResource.increment()
}
fun decrement() {
mCountingIdlingResource.decrement()
}
}
@Before
private fun registerIdlingResource() {
IdlingRegistry.getInstance().register(noteDetailActivityTestRule.activity.countingIdlingResource)
}
@After
fun unregisterIdlingResource() {
IdlingRegistry.getInstance().unregister(noteDetailActivityTestRule.activity.countingIdlingResource)
}
Copyright © 2019 Yahoo Japan Corporation. All Rights Reserved.
- 14. アイドリング状態になったらテ
スト開始
class SimpleCountingIdlingResource(resourceName: String) : IdlingResource {
private val mResourceName: String = checkNotNull(resourceName)
private val counter = AtomicInteger(0)
@Volatile
private var resourceCallback: IdlingResource.ResourceCallback? = null
override fun getName(): String {
return mResourceName
}
override fun isIdleNow(): Boolean {
return counter.get() == 0
}
override fun registerIdleTransitionCallback(resourceCallback: IdlingResource.ResourceCallback) {
this.resourceCallback = resourceCallback
}
fun increment() {
counter.getAndIncrement()
}
fun decrement() {
val counterVal = counter.decrementAndGet()
if (counterVal == 0) {
if (null != resourceCallback) {
resourceCallback!!.onTransitionToIdle()
}
}
if (counterVal < 0) {
throw IllegalArgumentException("Counter has been corrupted!")
}
}
}
Copyright © 2019 Yahoo Japan Corporation. All Rights Reserved.
- 15. onactivityresultに対してテストした
い
@Rule @JvmField
var addNoteIntentsTestRule = IntentsTestRule(AddNoteActivity::class.java)
@Test
fun addImageToNote_ShowsThumbnailInUi() {
val result : ActivityResult = createImageCaptureActivityResultStub()
intending(hasAction(MediaStore.ACTION_IMAGE_CAPTURE)).respondWith(result)
onView(withId(add_note_image_thumbnail)).check(matches(not(isDisplayed())))
selectTakeImageFromMenu()
onView(withId(add_note_image_thumbnail))
.perform(scrollTo())
.check(matches(allOf(
hasDrawable(),
isDisplayed())))
}
private fun selectTakeImageFromMenu() {
openActionBarOverflowOrOptionsMenu(getTargetContext())
onView(withText(take_picture)).perform(click())
}
private fun createImageCaptureActivityResultStub(): ActivityResult {
return ActivityResult(Activity.RESULT_OK, null)
}
Copyright © 2019 Yahoo Japan Corporation. All Rights Reserved.
- 16. まとめ
TDD
テストは大事
TDDはおすすめ
Espresso
とても直感的にUIテストが書ける
学習コストは低い気がする
他にも拡張機能が色々あり、WebViewとかもテストできる
Copyright © 2019 Yahoo Japan Corporation. All Rights Reserved.
Editor's Notes
- ユニットテストに適している