테스트 필요성
사용자는 버튼을 누르는 것부터 기기에 정보를 다운로드하는 것에 이르기까지 다양한 수준에서 앱과 상호작용합니다.
따라서 반복적으로 앱을 개발할 때 다양한 사용 사례와 상호작용을 테스트해야 합니다.
테스트용 코드 구성
앱이 확장됨에 따라 서버에서 데이터를 가져오거나, => MockWebServer??
기기 센서와 상호작용하거나, 로컬 저장소에 액세스하거나, => ???
복잡한 사용자 인터페이스를 렌더링해야 할 수 있습니다. => ???
앱 다양성을 고려하여 종합적인 테스트 전략을 수립해야 합니다.
반복적으로 코드 만들기 및 테스트
반복적으로 기능을 개발하는 경우 새 테스트를 작성하거나 기존 단위 테스트에 사례와 어설션을 추가하여 시작합니다.
새 기능을 디자인할 때 나타나는 책임 단위를 고려하여 개발하는 것이 중요합니다. 그 단위마다 해당하는 단위 테스트를 작성합니다.
단위 테스트는 표준 상호작용, 잘못된 입력, 사용 가능한 리소스가 없는 사례를 비롯한 단위와의 가능한 모든 상호작용을 다뤄야 합니다.
그림 1과 같이 전체 워크플로에는 길고 느린 UI 기반 주기가 코드 단위 통합을 테스트하는 일련의 중첩된 반복 주기가 포함되어 있습니다. 더 짧고 빠른 개발 주기를 사용하여 단위 자체를 테스트합니다. 이 주기 집합은 앱이 모든 사용 사례를 충족할 때까지 계속됩니다.
앱을 일련의 모듈로 보기
코드를 더 쉽게 테스트하려면 모듈 측면에서 코드를 개발하세요.
이 관점은 일반적으로 UI, 비즈니스 로직 및 데이터를 나타내는 레이어를 포함하는 앱의 스택 기반 관점과 대비됩니다.
ex) '작업 목록' 앱에는 작업을 만드는 모듈, 완료된 작업의 통계를 보는 모듈, 특정 작업과 관련된 사진을 찍는 모듈이 있을 수 있습니다.
이러한 모듈식 아키텍처는 관련이 없는 클래스를 분리된 상태로 유지하는 데 도움이 되며 개발팀 내에서 소유권을 할당하기 위한 자연 구조를 제공합니다.
모듈
- 모듈에는 하나의 중점 영역만 있어야 하며 모듈 간 통신을 허용하는 API가 일관되어야 합니다. |
여러 유형의 테스트 기기
- 실제 기기
- 가장 높은 충실도를 제공하지만 테스트를 실행하는 데 가장 많은 시간이 소요
- 가상 기기(예: 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의 구조 확인
- Espresso는 기기 또는 Robolectric에서 다음과 유사한 UI 상호작용을 실행할 때 작업을 동기화된 상태로 유지합니다.
- 대형 테스트(UI tests) : 앱의 여러 모듈에 걸쳐 사용자 여정의 유효성을 검사하는 엔드 투 엔드 테스트
- 대형 워크플로 기반 테스트의 경우 워크플로에 포함된 각 모듈의 기능을 확인하는 중형 테스트도 작성해야 합니다
- 여러 모듈 및 기능을 통해 사용자를 안내하는 엔드 투 엔드 워크플로의 유효성을 검사하는 것도 그만큼 중요합니다.
이러한 유형의 테스트는 코드에 피할 수 없는 병목 현상을 발생시키지만 가능한 실제 완제품에 가까운 앱의 유효성을 검사하여 이 영향을 최소화할 수 있습니다. - 실제 기기보다는 Firebase Test Lab과 같은 클라우드 기반 서비스 또는 에뮬레이션된 기기에서 앱을 테스트하는 것이 더 좋습니다.
Q. 앱의 구조와 다음 중형 테스트 예를 사용하여(범위 증가 순서로) 앱의 단위 그룹을 표현하는 가장 좋은 방법을 정의하세요.
|
Re: 이러한 테스트를 실행하려면 다음을 따르세요.
|
- Espresso는 중간 규모의 계측 테스트를 지원할 뿐만 아니라 대형 테스트에서 다음 작업을 완료할 때 동기화를 지원합니다.
필수 단위 테스트
모범 사례를 따를 때 다음과 같은 경우에 단위 테스트를 사용해야 합니다.
|
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