Espresso를 사용한 UI 테스트
Espresso로 자동화된 UI 테스트를 작성합니다. onView()로 뷰를 찾고 perform()으로 상호 작용하며 check()로 상태를 검증하고 RecyclerView 상호 작용을 테스트합니다.
Espresso를 사용한 UI 테스트은(는) CoddyKit의 무료 Android Academy 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Android Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Android Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
Espresso란 무엇인가요?
Espresso는 Android의 공식 UI 테스트 프레임워크입니다. 버튼을 누르고, 텍스트를 입력하고, 목록을 스크롤하는 등 앱의 UI와 상호작용하는 테스트를 작성하고 화면에 표시된 내용을 검증할 수 있습니다.
Espresso는 기기나 에뮬레이터에서 실행되는 계측 테스트이며, UI 스레드와 자동으로 동기화되므로 불안정한 sleep() 호출이 필요하지 않습니다.
설정
Espresso는 Android 테스트 도구 모음에 포함되어 있습니다. app/build.gradle에 다음 의존성을 추가합니다:
// app/build.gradle:
android {
defaultConfig {
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
}
dependencies {
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.5.1' // RecyclerView
}ActivityScenarioRule
각 테스트 전에 Activity를 실행하고 이후에 닫으려면 ActivityScenarioRule을 사용하세요:
@RunWith(AndroidJUnit4::class)
class LoginActivityTest {
@get:Rule
val activityRule = ActivityScenarioRule(LoginActivity::class.java)
@Test
fun `login button is displayed`() {
onView(withId(R.id.btnLogin))
.check(matches(isDisplayed()))
}
}onView()와 ViewMatchers
onView(matcher)는 현재 뷰 계층에서 뷰를 찾습니다. 정확도를 높이려면 여러 매처를 조합하세요:
// Match by ID:
onView(withId(R.id.tvTitle))
// Match by text:
onView(withText("Submit"))
// Match by content description (for accessibility):
onView(withContentDescription("Close dialog"))
// Combine matchers:
onView(allOf(withId(R.id.btnSave), isEnabled()))
// Inside a specific parent:
onView(withId(R.id.btnSave)).inRoot(isDialog())ViewActions — 뷰와 상호작용하기
뷰를 찾은 후 .perform()으로 동작을 수행합니다:
// Tap a button:
onView(withId(R.id.btnLogin)).perform(click())
// Type into an EditText:
onView(withId(R.id.etEmail))
.perform(typeText("alice@example.com"), closeSoftKeyboard())
// Clear text and retype:
onView(withId(R.id.etPassword))
.perform(clearText(), typeText("secret123"), closeSoftKeyboard())
// Scroll to a view:
onView(withId(R.id.btnSubmit)).perform(scrollTo(), click())
// Long press:
onView(withId(R.id.ivImage)).perform(longClick())ViewAssertions — 상태 검증하기
.check()로 화면에 표시된 내용을 확인합니다:
// View is displayed:
onView(withId(R.id.tvError)).check(matches(isDisplayed()))
// View has specific text:
onView(withId(R.id.tvTitle)).check(matches(withText("Welcome!")))
// View is not displayed (GONE or INVISIBLE):
onView(withId(R.id.progressBar)).check(matches(not(isDisplayed())))
// View is enabled:
onView(withId(R.id.btnSave)).check(matches(isEnabled()))
// View does not exist:
onView(withId(R.id.tvError)).check(doesNotExist())전체 로그인 테스트
사용자 인증 정보를 입력하고 로그인을 누르는 전체 테스트입니다:
@Test
fun `successful login shows home screen`() {
// Type email
onView(withId(R.id.etEmail))
.perform(typeText("alice@example.com"), closeSoftKeyboard())
// Type password
onView(withId(R.id.etPassword))
.perform(typeText("password123"), closeSoftKeyboard())
// Tap login button
onView(withId(R.id.btnLogin)).perform(click())
// Assert welcome message is shown
onView(withId(R.id.tvWelcome))
.check(matches(withText("Welcome, Alice!")))
}RecyclerView 테스트하기
espresso-contrib의 RecyclerViewActions를 사용해 목록 항목과 상호작용합니다:
import androidx.test.espresso.contrib.RecyclerViewActions
@Test
fun `clicking item opens detail screen`() {
// Scroll to position 5 and click:
onView(withId(R.id.recyclerView))
.perform(RecyclerViewActions.actionOnItemAtPosition<RecyclerView.ViewHolder>(
5, click()
))
// Assert detail screen is shown:
onView(withId(R.id.tvDetailTitle)).check(matches(isDisplayed()))
}입력 유효성 검사 테스트하기
입력이 유효하지 않을 때 오류 메시지가 표시되는지 검증합니다:
@Test
fun `empty email shows error message`() {
// Leave email blank, tap login
onView(withId(R.id.btnLogin)).perform(click())
// Assert error is shown
onView(withId(R.id.tilEmail))
.check(matches(hasDescendant(withText("Email is required"))))
}
@Test
fun `short password shows error`() {
onView(withId(R.id.etPassword))
.perform(typeText("123"), closeSoftKeyboard())
onView(withId(R.id.btnLogin)).perform(click())
onView(withId(R.id.tilPassword))
.check(matches(hasDescendant(withText("Minimum 6 characters"))))
}유휴 리소스
Espresso는 UI 스레드가 유휴 상태가 될 때까지 자동으로 기다리지만 네트워크 호출이나 코루틴은 기다리지 않습니다. 비동기 작업을 기다리도록 Espresso에 알리려면 IdlingResource를 사용하세요:
// CountingIdlingResource: increment before async work, decrement when done
val idlingResource = CountingIdlingResource("NetworkCall")
// In your ViewModel/Repository:
idlingResource.increment()
viewModelScope.launch {
loadData()
idlingResource.decrement()
}
// In test setUp:
@Before
fun setUp() {
IdlingRegistry.getInstance().register(idlingResource)
}
@After
fun tearDown() {
IdlingRegistry.getInstance().unregister(idlingResource)
}Espresso 테스트 실행하기
연결된 기기나 에뮬레이터에서 계측 테스트를 실행합니다:
- Android Studio에서: 테스트 클래스를 마우스 오른쪽 버튼으로 클릭 → 실행
- 터미널에서:
./gradlew connectedAndroidTest - 결과는
app/build/reports/androidTests/에 표시됩니다
안정적이고 빠르게 테스트를 실행하려면 Android Emulator API 28 이상을 사용하세요. 불안정한 테스트를 방지하려면 개발자 설정에서 애니메이션을 사용 중지하세요.
빠른 확인
뷰를 찾고 텍스트를 확인하는 올바른 Espresso 패턴은 무엇인가요?
복습: Espresso UI 테스트
자동화된 UI 테스트는 사용자가 발견하기 전에 기존 동작이 깨지는 문제를 찾습니다:
onView(matcher)— 뷰 찾기.perform(action)— 누르기, 입력하기, 스크롤하기.check(matches(...))— 표시 여부, 텍스트, 상태 검증하기- 목록과 상호작용하려면
RecyclerViewActions사용 - 비동기 작업에는
IdlingResource사용 - 불안정한 테스트를 방지하려면 시스템 애니메이션 사용 중지
다음: 전문가처럼 앱을 디버깅하고 프로파일링하는 방법입니다.
자주 묻는 질문
“Espresso를 사용한 UI 테스트” 강의는 무료인가요?
네 — “Espresso를 사용한 UI 테스트” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Android Academy 강의 전체를 잠금 해제할 수 있습니다. Android Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“Espresso를 사용한 UI 테스트”에서 뭘 배우나요?
Espresso로 자동화된 UI 테스트를 작성합니다. onView()로 뷰를 찾고 perform()으로 상호 작용하며 check()로 상태를 검증하고 RecyclerView 상호 작용을 테스트합니다. 브라우저에서 직접 실행하는 실습 코드로 Android Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Android Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Android Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.
“Espresso를 사용한 UI 테스트” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Android Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Android Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- JUnit을 사용한 단위 테스트
- Mockito를 사용한 모의 객체
- Espresso를 사용한 UI 테스트
- 디버깅과 프로파일링