탐색 테스트

1. 시작하기 전에

이전 Codelab에서는 활동 간 탐색에 관해 알아봤습니다. 이 Codelab에서는 계측 테스트를 사용하여 탐색을 테스트하는 다양한 접근 방식을 알아봅니다.

기본 요건

  • Android 스튜디오에서 테스트 디렉터리를 만들어 보았습니다.
  • Android 스튜디오에서 단위 테스트와 계측 테스트를 작성했습니다.

학습할 내용

  • 계측 테스트를 사용하여 활동이나 프래그먼트 간의 물리적 탐색을 테스트하는 방법

필요한 항목

  • Android 스튜디오가 설치된 컴퓨터
  • Words 앱의 솔루션 코드

이 Codelab의 시작 코드 다운로드

이 Codelab에서는 Words 앱 솔루션 코드에 계측 테스트를 추가합니다.

이 Codelab의 코드를 가져와서 Android 스튜디오에서 열려면 다음을 실행합니다.

코드 가져오기

  1. 제공된 URL을 클릭합니다. 브라우저에서 프로젝트의 GitHub 페이지가 열립니다.
  2. 프로젝트의 GitHub 페이지에서 Code 버튼을 클릭하여 대화상자를 엽니다.

5b0a76c50478a73f.png

  1. 대화상자에서 Download ZIP 버튼을 클릭하여 컴퓨터에 프로젝트를 저장합니다. 다운로드가 완료될 때까지 기다립니다.
  2. 컴퓨터에서 파일을 찾습니다(예: Downloads 폴더).
  3. ZIP 파일을 더블클릭하여 압축을 해제합니다. 프로젝트 파일이 포함된 새 폴더가 만들어집니다.

Android 스튜디오에서 프로젝트 열기

  1. Android 스튜디오를 시작합니다.
  2. Welcome to Android Studio 창에서 Open an existing Android Studio project를 클릭합니다.

36cc44fcf0f89a1d.png

참고: Android 스튜디오가 이미 열려 있는 경우 File > New > Import Project 메뉴 옵션을 대신 선택합니다.

21f3eec988dcfbe9.png

  1. Import Project 대화상자에서 압축 해제된 프로젝트 폴더가 있는 위치로 이동합니다(예: Downloads 폴더).
  2. 프로젝트 폴더를 더블클릭합니다.
  3. Android 스튜디오가 프로젝트를 열 때까지 기다립니다.
  4. Run 버튼 11c34fc5e516fb1c.png을 클릭하여 앱을 빌드하고 실행합니다. 예상대로 작동하는지 확인합니다.
  5. Project 도구 창에서 프로젝트 파일을 살펴보고 앱이 설정된 방식을 확인합니다.

2. 시작 앱 개요

Words 앱은 목록을 표시하는 홈 화면으로 구성되며 각 목록 항목은 알파벳 문자입니다. 문자를 클릭하면 클릭한 문자로 시작하는 단어 목록을 보여주는 화면으로 이동합니다.

3. 권장사항

Kotlin에서 함수 이름을 지정하는 일반적인 규칙은 함수 이름의 첫 번째 문자가 소문자이고 후속 단어의 첫 번째 문자가 대문자(예: myCamelCaseFunction())인 '카멜 표기법'을 사용하는 것입니다. 지금까지 작성한 테스트 메서드에서는 모두 소문자와 단어 사이에 밑줄(예: my_test_function())을 사용했습니다. 무엇을 테스트하는지 명시적으로 나타내기 위해 함수 이름이 상세하길 바랐기 때문입니다. 이렇게 하면 테스트에 실패할 경우 이름 자체에 실패한 항목이 명확하게 표시됩니다. Kotlin에서는 ``test function with spaces()와 같이 메서드 이름을 백틱으로 래핑하는 경우 메서드 이름에 공백도 사용할 수 있습니다. 백틱은 작은따옴표와 다릅니다. 물결 표시(~)가 있는 키에서 확인할 수 있습니다. 이를 통해 오류가 발생할 때 식별하기 쉬운, 사람이 읽을 수 있는 함수 이름을 만들 수 있습니다.

그러나 이 접근 방식에는 주의할 점이 있습니다. 구현하려면 몇 가지 설정이 필요하다는 점입니다. 이 섹션은 선택사항입니다. 읽어보는 것이 좋지만 계측 테스트 디렉터리 만들기 섹션까지 단계를 따를 필요는 없습니다.

  1. 함수 이름에 공백을 사용하는 것은 Android에서 API 30을 타겟팅하는 경우에만 작동합니다. 그 외 경우에는 다음과 같은 오류가 발생합니다.

4333fe8605801dba.png

API를 변경하려면 app/build.gradle로 이동하여 minSdkVersiontargetSdkVersion을 수정합니다.

a6207c31c66ca185.png

이 경우 targetSdkVersion은 요구사항인 30으로 설정합니다. 그러나 minSdkVersion19이므로 함수 이름에 공백을 허용하려면 30으로 변경해야 합니다. 이는 실용적이지 않을 때도 있으므로 '있으면 좋은' 기능이긴 하나 요구사항은 아닙니다.

  1. API 30을 타겟팅하더라도 메서드에 'Identifier not allowed in Android Projects'라는 메시지와 함께 빨간색으로 밑줄이 그어져 있는 것을 확인할 수 있습니다.

d1330d69cc2472b1.png

테스트는 여전히 완료될 때까지 실행되지만 밑줄을 제거하려면 Android 스튜디오 설정/환경설정으로 이동하여 Editor -> Inspections -> Kotlin Android -> Illegal Android Identifier -> Tests로 이동합니다.

acc4a31499bdb25.png

그런 다음 Tests 체크박스를 선택 해제하고 Apply 또는 OK를 클릭합니다.

aeb57d303996a3de.png

이제 메서드 이름을 백틱으로 묶는 한 메서드에 더 이상 빨간색 밑줄이 표시되지 않습니다.

a54f3eff47697024.png

4. 테스트 디렉터리 만들기

Words 앱의 계측 테스트 디렉터리를 만듭니다.

5. 계측 테스트 클래스 만들기

NavigationTests.kt라는 새 클래스를 만듭니다.

9d9ee307b4773b7.png

6. 탐색 테스트 작성

  1. 테스트 실행기를 지정합니다.
@RunWith(AndroidJUnit4::class)
  1. 그런 다음 기본 활동을 실행합니다.
@get:Rule
val activity = ActivityScenarioRule(MainActivity::class.java)
  1. 이제 navigate_to_word()라는 메서드를 만듭니다.
@Test
fun navigate_to_word() {
}
  1. navigate_to_word() 메서드에서 선택할 목록 항목을 정해야 합니다. 선택하는 항목은 임의적이며 여러 가지 방법으로 실행할 수 있습니다. 어댑터 내의 위치에 따라 항목을 선택하거나, 포함된 텍스트(문자)에 따라 항목을 선택할 수 있습니다. RecyclerView와 직접 상호작용하려면 다음 종속 항목이 필요합니다.
dependencies {
    ...
    androidTestImplementation
‘com.android.support.test.espresso:espresso-contrib:3.0.2'
}

반면 텍스트로 항목을 선택하려면 이전 Codelab에서 사용한 withText() 메서드를 사용하면 됩니다. 이 접근 방식을 사용하는데 텍스트가 화면에 표시되지 않으면 테스트가 실패한다는 점에 유의해야 합니다. 이 내용은 나중에 살펴보겠습니다.

  1. 두 가지 방법 모두로 시도할 수 있는지 확인합니다. UI 구성요소가 검색되면 이를 클릭하는 것이 목표입니다.

문자 'C'의 항목을 예로 클릭하는 의도로 두 접근 방식이 모두 여기에 표시됩니다.

onView(withText("C")).perform(click())
onView(withId(R.id.recycler_view))
   .perform(RecyclerViewActions
       .actionOnItemAtPosition<RecyclerView.ViewHolder>(2, click()))

잠시 시간을 내어 이 두 가지 접근 방식을 자세히 살펴보세요. 두 가지 방법 중 하나를 실행하고 에뮬레이터나 기기를 살펴보면 두 가지 모두 작동하는 것을 확인할 수 있습니다. RecyclerViewActions를 사용하려면 코드가 더 많이 필요하지만 추가 작업 없이 항목을 클릭할 수 있다는 뚜렷한 이점이 있습니다. 첫 번째 접근 방식을 시도하되 문자 'C'를 'Z'로 변경하고 테스트를 다시 실행합니다. 다음 오류와 함께 테스트가 실패하는 것을 확인할 수 있습니다. androidx.test.espresso.NoMatchingViewException: No views in hierarchy found matching: with text: is "Z"

3c518d4b00624af3.png

'Z'가 목록의 맨 끝에 있고 앱을 실행할 때 화면 밖에 있어서 스크롤해야 하기 때문입니다. RecyclerViewAction 접근 방식은 기본적으로 이를 처리합니다. 25를 위치 값으로 전달해 보고 에뮬레이터나 기기를 확인합니다.

  1. 위의 예를 실행하면 다음 활동을 성공적으로 실행했음을 확인할 수 있지만, 어설션을 사용하여 이를 확인하고자 합니다. 앱 자체를 실행하고 지정된 목록 항목을 클릭하면 앱 바의 제목이 'Words That Start With __'라고 표시됩니다. 여기서 빈 공간은 클릭한 문자입니다. 이를 사용하여 탐색이 올바르게 작동했는지 확인할 수 있습니다. 올바른 문자열 뒤에 클릭한 문자가 표시되는지 어설션하기만 하면 됩니다. 이전 Codelab에서 유사한 어설션을 만들었으므로 직접 할 수 있는지 확인해 보세요.
onView(withText("Words That Start With C")).check(matches(isDisplayed()))

7. 개념 강의 및 권장사항

테스트에 사용되는 매우 중요한 용어에는 '거짓양성'과 '거짓음성' 두 가지가 있습니다.

'거짓양성'은 문제가 발생하여 테스트가 실패해야 함에도 테스트 결과가 통과로 나오는 경우입니다. 마찬가지로 '거짓음성'은 모든 항목이 올바르고 테스트에 통과해야 할 때 테스트 결과가 실패로 나오는 경우입니다.

위에서 작성한 테스트에서 찾고 있던 문자열을 하드 코딩했습니다. 코드 관점에서는 앱에서 했던 것처럼 문자열 리소스에서 문자열을 빌드하는 것이 더 깔끔합니다. 이는 일반 앱 코드에서와 약간 다르게 작동하지만 여전히 가능합니다. 그러나 이 방식으로 문자열을 빌드하면 잠재적으로 실패할 수 있습니다. 문자열 빌드가 기술적으로 비즈니스 로직이기 때문입니다. 테스트에서 문자열을 빌드하는 것이 앱 코드에서 실패한 것과 같은 방식으로 실패하면 거짓양성이 발생할 수 있습니다. 이는 두 코드가 모두 같은 문자열을 잘못 빌드하여 테스트의 잘못된 텍스트가 앱에 표시된 잘못된 텍스트와 일치하기 때문입니다. 따라서 문자열을 예상하는 값으로 하드 코딩하는 것이 더 좋습니다.

8. 솔루션 코드

9. 축하합니다

이 Codelab에서 배운 내용은 다음과 같습니다.

  • 테스트를 위한 상세한 함수 이름을 만드는 방법을 알아봤습니다.
  • 활동 또는 프래그먼트로 물리적 탐색을 테스트하는 방법을 알아봤습니다.
  • '거짓양성'과 '거짓음성'에 관해 알아봤습니다.