Espresso란?
1. UI 테스팅 기초
gradel 설정
android {
defaultConfig {
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" // 기존에 있음
}
}
dependencies {
androidTestImplementation 'androidx.test:rules:1.2.0'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'// 기존에 있음
androidTestImplementation 'androidx.test.espresso:espresso-accessibility:3.3.0-alpha05'
}
Test code 작성
mainActivity
class MainActivity : AppCompatActivity() {
val count = ObservableInt(0)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding: ActivityMainBinding = DataBindingUtil.setContentView(
this,
R.layout.activity_main
)
binding.count = count
binding.addButton.setOnClickListener {
count.set(count.get() + 1)
}
binding.subtractButton.setOnClickListener {
count.set(count.get() - 1)
}
}
}
TestCode
@RunWith(AndroidJUnit4::class)
class CounterInstrumentedTest {
@Rule
@JvmField
var mActivityTestRule: ActivityTestRule<MainActivity> = ActivityTestRule(MainActivity::class.java)
@Test
fun testIncrement() {
Espresso.onView(withId(R.id.add_button)) // 1) 뷰 계층 구조에서 하나 이상의 뷰를 찾습니다 (추가 버튼).
.perform(ViewActions.click()) // 2) 어떤 방식 으로든 view들과 상호 작용합니다 (클릭 수행).
Espresso.onView(withId(R.id.countTV))
.check(matches(withText("1")))
}
// 3) UI의 상태에 대한 assertion을 작성하십시오 (업데이트 된 개수가 표시됨을 assert 함).
companion object {
@BeforeClass
@JvmStatic
fun enableAccessibilityChecks() {
// TODO: uncomment to enable accessibility checks.
// AccessibilityChecks.enable()
}
}
}
1) 뷰 계층 구조에서 하나 이상의 뷰를 찾습니다(추가 버튼).
2) 어떤 방식 으로든 view들과 상호 작용합니다(클릭 수행).
3) UI의 상태에 대한 assertion을 작성하십시오 (업데이트 된 개수가 표시됨을 assert 함).
2. 앱의 접근성을 평가
접근성 테스트 프레임 워크 ( ATF )를 통해 앱의 접근성을 평가한다.
Espresso의 메인 컴포넌트
1. Espresso
- onView() 와 onData() 를 통해 뷰와 상호작용 할 수 있는 엔트리 포인트입니다.
- 뷰에 대한 접근이 필수는 아니며, pressBack() 같은 메소드도 있습니다.
onView, check, perform
에스프레소에서 사용하는 기본 함수들로,
onView : 대상 view 찾고
- id와 텍스트로 찾는 방법이 있음
.onView(withId(R.id.button)) // 에서 id 가 button 인 뷰를 화면에서 찾는다
.onView(withText("Welcome")) // "Welcome" 이란 텍스트를 가진 뷰를 찾는다
check : view의 상태를 확인
찾기만 할 경우 못찾아도 아무런 에러가 발생하지 않기에 '꼭' check 함수로 확인을 해주어야 함
.check(matches(isDisplayed()))
.check(matches(withText("Welcome")))
.check(matches(allOf(isDisplayed(),withText("Welcome"))))
perform : view에게 특정 동작시킴
- 해당 뷰가 할 수 있는 동작이 아닐 경우는 실행 시점에서 에러가 발생
.perform(click())
.perform(click(), longClick())
2. ViewMatcher : Find a View
- Matcher<? super View> 인터페이스를 구현한 클래스들의 집합입니다.
- onView()의 파라미터로 사용되며, 예시로 withId() 등이 있습니다.
- ViewMatchers는 뷰를 찾기 위해서도 ( onView ) 쓰고, 뷰의 상태를 확인하기 ( check ) 위해서도 사용한다.
- 대다수의 경우에 onView() 메소드는 하나의 View에 매칭되는 hamcrest matcher를 취합니다.
onView(withText("Welcome"))
.check(matches(allOf(isDisplayed(),withText("Welcome"))))
// isDisplayed()
onView(isDisplayed())
// withId()
onView(withId(R.string.button))
// withText()
onView(withText("Button"))
// withText()
onView(withText(R.string.button))
// withText()
onView(withText(object : CustomMatcher<String>("has multiple 't'"){
override fun matches(item: Any?): Boolean {
return (item as? String)?.let{
it.filter { it == 't' }.count() == 2
}?: false
}
}))
그외..
hasContentDescription, withContentDescription
withParent, withChild, hasSibling, hasDescendant
isAssignableFrom
isClickable, isEnabled, isSelected, withClassName
3. ViewActions : Perform an action on a view
- ViewAction 인터페이스를 구현한 클래스들의 집합입니다.
- ViewInteraction.perform() 메소드의 파라미터로 쓰이며, 예시로 click() 등이 있습니다.
클릭 동작
// 클릭 -> 롱 클릭 -> 더블 클릭이 순차적으로 일어난다.
onView(withId(R.id.button))
.perform(click(), longClick())
.perform(doubleClick())
텍스트 타이핑 동작
onView(withId(R.id.editText))
.perform(clearText()) // clearText()텍스트를 지우는 동작을 하고,
.perform(typeText("Hello")) // typeText()타이핑하는 동작
.perform(typeTextIntoFocusedView("World")) // typeTextIntoFocusedView()타이핑하는 동작
onView(withId(R.id.editText))
.perform(replaceText("Hello World")) //텍스트를 대체 >> Hello World
.perform(typeTextIntoFocusedView("!!")) // 맨 앞에 글자를 쓰기 시작 >> !!Hello World
스크롤(scroll)
onView(withId(R.id.editText))
.perform(scrollTo(), click())
스와이프(swipe)
perform(swipeUp(), swipeDown(), swipeRight(), swipeLeft())
불변해야하는 뷰 처리
val viewAssertion = matches(withId(R.id.button))
addGlobalAssertion("button always isDisplayed",viewAssertion)
removeGlobalAssertion(viewAssertion)
반복 행동 처리
repeatedlyUntil
onView(withId(R.id.button))
.perform(repeatedlyUntil(click(), hasSibling(withText("Welcome")), 10))
키보드 처리
closeSoftKeyboard, pressImeActionButton, pressKey, pressBack
링크 관련 처리
openLink, openLinkWithUri
4. ViewAssertions : Perform an action on a view
- ViewAssertion 인터페이스를 구현한 클래스들의 집합입니다.
- ViewInteraction.check() 메소드의 파라미터로 쓰이며, 예시로 matches() 등이 있습니다.
// matches()
onView(withId(R.id.textView))
.check(matches(not(withText("Hello World!"))))
onView(withText("Barabarabarabam"))
.check(doesNotExist())
onView(withId(R.id.linearLayout))
.check(
selectedDescendantsMatch(
isAssignableFrom(TextView::class.java),
hasContentDescription()
)
)
Samples Code
- IntentsBasicSample: Basic usage of intended() and intending().
- IdlingResourceSample: Synchronization with background jobs.
- BasicSample: Basic Espresso sample.
- CustomMatcherSample: Shows how to extend Espresso to match the hint property of an EditText object.
- DataAdapterSample: Showcases the onData() entry point for Espresso, for lists and AdapterView objects.
- IntentsAdvancedSample: Simulates a user fetching a bitmap using the camera.
- MultiWindowSample: Shows how to point Espresso to different windows.
- RecyclerViewSample: RecyclerView actions for Espresso.
- WebBasicSample: Use Espresso-Web to interact with WebView objects.
- BasicSampleBundled: Basic sample for Eclipse and other IDEs.
참고
'Android > Android Test' 카테고리의 다른 글
[codelab 5.1 -8 9 10]AndroidX 테스트로 ViewModel(LiveData 관찰되는지) 테스트 (0) | 2021.05.03 |
---|---|
[codelab 5.1 - 5 6 7] Android Test 종류, [일반 클래스] Local Unit Test, TDD (0) | 2021.05.03 |
Android Test관련 실습 예제 및 소스 목록 (1) | 2021.04.26 |
Android Test 디자인 (Droid Knights 2018 발표 내용 정리하기) (0) | 2021.04.24 |
Android에서 앱 테스트 (Test apps on Android) (0) | 2021.04.21 |