Android/TDD

Android 테스트 구조/구성 개념잡기

네모메모 2023. 8. 15. 17:05
반응형

테스트 필요성

사용자는 버튼을 누르는 것부터 기기에 정보를 다운로드하는 것에 이르기까지 다양한 수준에서 앱과 상호작용합니다.

따라서 반복적으로 앱을 개발할 때 다양한 사용 사례와 상호작용을 테스트해야 합니다.

 


테스트용 코드 구성

앱이 확장됨에 따라 서버에서 데이터를 가져오거나, => MockWebServer??

기기 센서와 상호작용하거나, 로컬 저장소에 액세스하거나, => ???

복잡한 사용자 인터페이스를 렌더링해야 할 수 있습니다. => ???

앱 다양성을 고려하여 종합적인 테스트 전략을 수립해야 합니다.

반복적으로 코드 만들기 및 테스트

반복적으로 기능을 개발하는 경우 새 테스트를 작성하거나 기존 단위 테스트에 사례와 어설션을 추가하여 시작합니다.

새 기능을 디자인할 때 나타나는 책임 단위를 고려하여 개발하는 것이 중요합니다. 그 단위마다 해당하는 단위 테스트를 작성합니다.

단위 테스트는 표준 상호작용, 잘못된 입력, 사용 가능한 리소스가 없는 사례를 비롯한 단위와의 가능한 모든 상호작용을 다뤄야 합니다.

 

그림 1. 반복적인 테스트 기반 개발과 관련된 두 개의 주기

그림 1과 같이 전체 워크플로에는 길고 느린 UI 기반 주기가 코드 단위 통합을 테스트하는 일련의 중첩된 반복 주기가 포함되어 있습니다. 더 짧고 빠른 개발 주기를 사용하여 단위 자체를 테스트합니다. 이 주기 집합은 앱이 모든 사용 사례를 충족할 때까지 계속됩니다.

 

앱을 일련의 모듈로 보기

코드를 더 쉽게 테스트하려면 모듈 측면에서 코드를 개발하세요.

이 관점은 일반적으로 UI, 비즈니스 로직 및 데이터를 나타내는 레이어를 포함하는 앱의 스택 기반 관점과 대비됩니다.

ex) '작업 목록' 앱에는 작업을 만드는 모듈, 완료된 작업의 통계를 보는 모듈, 특정 작업과 관련된 사진을 찍는 모듈이 있을 수 있습니다.

이러한 모듈식 아키텍처는 관련이 없는 클래스를 분리된 상태로 유지하는 데 도움이 되며 개발팀 내에서 소유권을 할당하기 위한 자연 구조를 제공합니다.

모듈
: 사용자가 앱 내에서 완료하는 특정 작업

- 모듈에는 하나의 중점 영역만 있어야 하며 모듈 간 통신을 허용하는 API가 일관되어야 합니다.
- 이러한 모듈 간 상호작용을 보다 쉽고 빠르게 테스트하려면 모듈의 가짜 구현을 만들어 보세요.
   => 테스트에서 한 모듈의 실제 구현이 다른 모듈의 가짜 구현을 호출할 수 있습니다.

- 앱에서 모듈을 정의하는 방법과 모듈을 만들고 게시하기 위한 플랫폼 지원에 관한 자세한 내용은 Android App Bundle을 참조하세요.
- 새 모듈을 만들 때 당장 모든 기능을 갖추려고 너무 고집을 부리지 마세요. 특정 모듈에 하나 이상의 앱 스택 레이어가 없어도 괜찮습니다 :)

 


여러 유형의 테스트 기기

  • 실제 기기
    • 가장 높은 충실도를 제공하지만 테스트를 실행하는 데 가장 많은 시간이 소요
  • 가상 기기(예: Android 스튜디오의 에뮬레이터)
    • 기기는 낮은 충실도 대신 향상된 테스트 속도를 제공
    • 충실도와 속도 간 균형을 제공
    • 가상 기기를 사용하여 테스트하는 경우 테스트 간 설정 시간을 최소화하려면 스냅샷을 사용하세요.
  • 시뮬레이션된 기기(예: Robolectric)
    •  플랫폼의 바이너리 리소스 및 사실적 루퍼 개선으로 시뮬레이션된 기기가 보다 사실적인 결과를 생성할 수 있습니다.
    • Robolectric :  안드로이드에 빠르고 신뢰성 높은 유닛 테스트를 지원해주는 테스트 프레임워크. 테스트는 수 초 내로 JVM 위에서 동작합니다.

테스트를 만들 때 '실제 개체' 또는 '테스트 더블'을 만드는 옵션이 있습니다.

테스트 더블(Test doubles)

: 소프트웨어 테스트에서 사용되는 여러 종류의 가짜 객체 또는 모의 객체를 가리키는 용어

- ex) 모조 개체 또는 모의 개체

- 개별적으로 테스트하려면 일반적으로 "Test doubles"라고 하는 가짜 또는 모의 종속성으로 테스트 대상의 종속성을 대체해야 하는 경우가 많습니다

- 가짜 객체들은 실제 컴포넌트와 상호작용하며 테스트 동안 예상된 동작을 시뮬레이션하고, 의존성을 분리하여 테스트의 격리성과 예측 가능성을 향상시키는데 도움을 줍니다.

- 테스트 더블에 관한 설명

더보기

특히 테스트 중인 개체가 다음 조건 중 하나를 충족하는 경우, 일반적으로 실제 개체를 테스트에 사용하는 것이 더 좋습니다.

  • 개체가 데이터 개체입니다.
  • 실제 개체 버전의 종속성과 통신하지 않으면 개체가 작동할 수 없습니다. 이벤트 콜백 핸들러가 좋은 예입니다.
  • 개체와 종속성의 통신을 복제하기 어렵습니다. 메모리 내 데이터베이스가 가짜 데이터베이스 결과보다 더 강력한 테스트를 제공하는 SQL 데이터베이스 핸들러가 좋은 예입니다.

 

더보기

테스트가 실제 객체에서 다음과 같은 유형의 작업을 하려는 경우 가짜 또는 모의 객체를 만드는 것이 좋습니다.

  • 시간이 오래 걸리는 작업(예: 대용량 파일 처리)
  • 밀폐되지 않은 작업(예: 임의의 열린 포트에 연결)
  • 만들기 어려운 구성

테스트 피라미드

- 앱이 세 개의 테스트 카테고리(소형, 중형, 대형)를 포함하는 방식을 보여줍니다.

- 소형 테스트(Unit tests)에서 대형 테스트(UI tests)로 피라미드를 올라가면 각 테스트의 충실도가 증가하지만 실행 시간과 유지보수 및 디버깅에 드는 노력도 증가합니다.
따라서 통합 테스트(Integration tests)보다 단위 테스트(Unit tests)를 더 많이 작성하고 엔드 투 엔드 테스트보다 통합 테스트를 더 많이 작성해야 합니다.

각 카테고리의 테스트 비율은 앱의 사용 사례에 따라 다를 수 있지만 일반적으로 소형 70%, 중형 20% 및 대형 10%로 카테고리를 나누는 것이 좋습니다.

- Android 테스트 피라미드에 관해 자세히 알아보려면 Google I/O 2017의 Test-Driven Development on Android 세션 동영상(1분 51초 지점부터)을 참조하세요.

 

 

 

그림 2. 앱의 테스트 모음에 포함해야 하는 세 개의 테스트 카테고리를 보여주는 테스트 피라미드

 

 

  • 소형 테스트(Unit tests) : 한 번에 한 클래스씩 앱 동작의 유효성을 검사하는 단위 테스트
    • 앱 내 각 클래스의 기능 및 계약을 철저하게 검증하는 고도로 집중된 단위 테스트
    • 특정 클래스 내에 메서드를 추가하고 변경할 때 메서드에 관한 단위 테스트를 만들고 실행하세요.
    • 테스트가 Android 프레임워크에 종속되었다면 -> 기기에 구속되지 않는 통합 API(예: androidx.test API)를 사용하세요.
    • 테스트가 리소스에 의존한다면 ->  앱의 build.gradle 파일에서 includeAndroidResources 옵션을 사용 설정하세요. 
    • 종류
      1. Local unit tests(로컬 단위 테스트)

      2. Instrumented tests(계측 테스트)
  • 중형 테스트(Integration tests) :  모듈 내의 스택 수준 간 상호작용 또는 관련 모듈 간 상호작용의 유효성을 검사하는 통합 테스트
    • 모듈 수준에서 앱 동작의 유효성을 검사
    • 단위 그룹의 공동작업 및 상호작용 유효성을 검사함
    • 계측 중형 테스트 실행 시 Espresso 사용 
      • Espresso는 기기 또는 Robolectric에서 다음과 유사한 UI 상호작용을 실행할 때 작업을 동기화된 상태로 유지합니다.
        • View 객체에 관한 작업 실행
        • 접근성 기능이 필요한 사용자가 앱을 사용하는 방법 평가 
        • RecyclerView 및 AdapterView 객체 내에서 항목 찾기 및 활성화 
        • 발신 인텐트 상태의 유효성 검사 
        • WebView 객체 내 DOM의 구조 확인
  • 대형 테스트(UI tests) : 앱의 여러 모듈에 걸쳐 사용자 여정의 유효성을 검사하는 엔드 투 엔드 테스트
    • 대형 워크플로 기반 테스트의 경우 워크플로에 포함된 각 모듈의 기능을 확인하는 중형 테스트도 작성해야 합니다
    • 여러 모듈 및 기능을 통해 사용자를 안내하는 엔드 투 엔드 워크플로의 유효성을 검사하는 것도 그만큼 중요합니다.
      이러한 유형의 테스트는 코드에 피할 수 없는 병목 현상을 발생시키지만 가능한 실제 완제품에 가까운 앱의 유효성을 검사하여 이 영향을 최소화할 수 있습니다.
    • 실제 기기보다는 Firebase Test Lab과 같은 클라우드 기반 서비스 또는 에뮬레이션된 기기에서 앱을 테스트하는 것이 더 좋습니다.

 

Q. 앱의 구조와 다음 중형 테스트 예를 사용하여(범위 증가 순서로) 앱의 단위 그룹을 표현하는 가장 좋은 방법을 정의하세요.
  1. 뷰와 뷰 모델 간의 상호작용(예: Fragment 객체 테스트, 레이아웃 XML 유효성 검사 또는 ViewModel 객체의 데이터 결합 로직 평가)
  2. 다양한 데이터 소스 및 데이터 액세스 객체(DAO)가 예상대로 상호작용하는지 확인하는 앱 저장소 레이어의 테스트
  3. 특정 화면의 상호작용을 테스트하는 앱의 세로 슬라이스. 이러한 테스트는 앱 스택의 레이어 전반에서 상호작용을 확인합니다.
  4. 앱의 특정 영역을 평가하는 다중 프래그먼트 테스트. 이 목록에 언급된 다른 유형의 중형 테스트와는 달리 일반적으로 이 유형의 테스트에는 실제 기기가 필요합니다. 테스트 중인 상호작용에 여러 UI 요소가 포함되어 있기 때문입니다.
Re: 이러한 테스트를 실행하려면 다음을 따르세요.
  1. Espresso Intents 라이브러리의 메서드를 사용합니다. 이러한 테스트에 전달하는 정보를 단순화하려면 가짜 객체 및 스터브를 사용합니다.
  2. IntentSubject와 Truth 기반 어설션을 함께 사용하여 캡처된 인텐트를 확인합니다.

 

 

 

- Espresso 중간 규모의 계측 테스트를 지원할 뿐만 아니라 대형 테스트에서 다음 작업을 완료할 때 동기화를 지원합니다.

 

 


필수 단위 테스트

모범 사례를 따를 때 다음과 같은 경우에 단위 테스트를 사용해야 합니다.

  • ViewModels 또는 발표자 에 대한 단위 테스트 .
  • 데이터 계층, 특히 리포지토리 에 대한 단위 테스트입니다 . 대부분의 데이터 계층은 플랫폼 독립적이어야 합니다. 이렇게 하면 test double이 테스트에서 데이터베이스 모듈과 원격 데이터 소스를 대체할 수 있습니다. Android에서 테스트 복식 사용 에 대한 가이드를 참조하세요.
  • 사용 사례 및 인터랙터와 마찬가지로 도메인 계층 과 같은 다른 플랫폼 독립적 계층에 대한 단위 테스트입니다 .
  • 문자열 조작 및 수학 같은 유틸리티 클래스 에 대한 단위 테스트 .

 

UI 테스트

사용해야 하는 몇 가지 유형의 UI 테스트가 있습니다.

  • 화면 UI 테스트는 단일 화면에서 중요한 사용자 상호 작용을 확인합니다. 
    버튼 클릭, 양식 입력, 보이는 상태 확인과 같은 작업을 수행합니다. 화면당 하나의 테스트 클래스가 좋은 시작점입니다.
  • 가장 일반적인 경로를 다루는 사용자 흐름 테스트 또는 탐색 테스트 . 
    이러한 테스트는 탐색 흐름을 통해 이동하는 사용자를 시뮬레이션합니다. 초기화 시 런타임 충돌을 확인하는 데 유용한 간단한 테스트입니다.

 

에지 케이스 테스트

: 인간 테스터와 더 큰 테스트가 포착할 가능성이 낮은 드문 시나리오

더보기

예를 들면 다음과 같습니다.

  • 음수, 0 및 경계 조건을 사용하는 수학 연산 .
  • 가능한 모든 네트워크 연결 오류.
  • 형식이 잘못된 JSON과 같은 손상된 데이터.
  • 파일에 저장할 때 전체 저장소를 시뮬레이션합니다.
  • 프로세스 중간에 다시 생성된 객체(예: 장치가 회전할 때의 활동).

 

피해야 할 단위 테스트

일부 단위 테스트는 값이 낮기 때문에 피해야 합니다.

더보기
  • 코드가 아닌 프레임워크 또는 라이브러리의 올바른 작동을 확인하는 테스트입니다.
  • 활동, 프래그먼트 또는 서비스와 같은 프레임워크 진입점에는 비즈니스 로직이 없어야 하므로 단위 테스트가 우선 순위가 되어서는 안 됩니다. 활동에 대한 단위 테스트는 대부분 프레임워크 코드를 다루고 보다 복잡한 설정이 필요하기 때문에 가치가 거의 없습니다. UI 테스트와 같은 계측 테스트는 이러한 클래스를 다룰 수 있습니다.

 

 

 


출처

https://developer.android.com/studio/test/test-in-android-studio?hl=ko 

https://developer.android.com/training/testing/fundamentals?hl=ko 

 

반응형