본 포스팅은 DroidKaigi 2017 ~ 変更に強いEspressoテストコードを効率良く書こう 을 기본으로 번역하여 작성했습니다
제 일본어 실력으로 인하여 오역이나 오타가 발생할 수 있습니다.
2017.03.09
sumio_tym
Android UI 테스트 도구 Espresso에 대해서 아래를 소개합니다
제품의
사양 변경에 강한
테스트를 Espresso Test Recorder를 사용해효율적으로
적는 방법
소개
효율적으로 테스트를 적는 것
테스트 자동화의 목적은 여러 가지 있다
공수를 줄이고
싶다오류를 없애고 싶다
안심하고 싶다
테스트를 쓰는데 시간을 소비한다
면 목적 달성이 어렵게 된다효율적으로(즐겁게) 테스트를 작성
하는 것도 중요조작 대상의 특정이 어렵다
(예) 다이얼로그의 메시지 문자열을 검증한다
조건 : 자손에게 “결과”라는 text를 가진 View의 형제가 자신의 조상에 있으며, 또한 자신은 TextView이다
↓ 를 스스로 생각해내는 것은 솔직히 어렵다…
onView(allOf(
withClassName(
is(TextView.class.getName())),
isDescendantOfA(hasSibling(
hasDescendant(
withText("결과"))))))
.check(matches(
withText("3 + 4 = 7")));
Espresso Test Recorder
그렇지만, 잘 안되는 케이스도…
가능한
Espresso Test Recorder가 잘하는
테스트 케이스를 자동화 대상으로 한다
자동화의 목적에서 벗어나지 않았는가
의 검토는 필요합니다.그래서 알아두면 좋은 것은?
나중에 소개합니다!
소개
변경에 강한 테스트를 적는 것
화면의 사양 변경이 발생했을 때에 테스트 코드 수정 임팩트가 작은
것
약한
테스트의 전형적인 사례많은 테스트 케이스에 복사
되어 있는 경우약한
테스트의 전형적인 사례로그인 화면의 테스트 케이스를 생각한다
"로그인"
이라고 표시된 버튼을 누르면 ~ 되는 것"로그인"
이라고 표시된 버튼을 누르면 ~ 되는 것"로그인"
이라고 표시된 버튼을 누르면 ~ 되는 것나중에 “로그인” 버튼이 “OK” 버튼으로 사양 변경되면 전부 수정이 필요!
Espresso Test Recorder로 평범하게 기록하면 이렇게 된다!
강하게
하기 위해서는? (이미지)같은 조작을 공통부분으로 추출한다
로그인하면
~ 되는 것로그인하면
~ 되는 것로그인하면
~ 되는 것※ 여기에서, “로그인한다” = “로그인”이라고 표시된 버튼을 누른다
나중에 “로그인” 버튼이 “OK” 버튼으로 사양 변경되어도 “※” 만 수정하면 OK
cf. PageObject 디자인 패턴
Espresso Test Recorder로 기록한 경우, 공통부분의 추출은 수작업으로 해야할 필요가 있다!
아래를 숙달되면 부담이 줄어든다
구체적인 수정방침
을 생각한다자주 사용하는
Android Studio의 리팩터 기능
을 외운다(키보드 단축키
도 외운다)나중에 소개합니다!
효율적으로 테스트를 쓰기 위해서는
변경에 강한 테스트로 하기 위해서는
Espresso 기본
(※) https://developer.android.com/training/testing/espresso/cheat-sheet.html 로부터 로고를 인용
빌드 환경 설정
(https://goo.gl/WlXSCq)
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2',
{
exclude group: 'com.android.support', module: 'support-annotations'
}
)
프로덕트 코드와 충돌하는 모듈을 제외한다. (빌드 에러시의 메시지 참조)
androidTestCompile( 'com.android.support.test.espresso:espresso-contrib:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
exclude group: 'com.android.support', module: 'support-v4'
exclude group: 'com.android.support', module: 'appcompat-v7'
exclude group: 'com.android.support', module: 'design'
exclude group: 'com.android.support', module: 'recyclerview-v7'
}
)
테스트 실행 단말의 애니메이션 설정
(“개발자 옵션”의 아래를 OFF한다)
※ Espresso Test Recorder가 서식을 자동 생성
@RunWith(AndroidJUnit4.class)
public class MyEspressoTest {
@Rule public ActivityTestRule<...> activityTestRule = ...;
...
}
onView(ViewMatcher)
.perform(ViewAction)
.check(ViewAssertion);
이미 존재하는 API 목록은 치트 시트(https://goo.gl/sH9eax 참조
onData()
RecyclerViewActions
DrawerActions · NavigationViewActions
PickerActions
onWebView()
View 프로퍼티를 동적으로 취득
(사전에 알고 있는 값과 일치확인은 가능하다)
조작 · 확인대상이 명확하지 않은 케이스
AsyncTask이외의 비동기 대기
환경설정은
Espresso Test Recorder에 맡기는 것이 편하다
대부분의 UI 부품 조작 · 확인을 지원
아래에 대해서는 다가가지 않는 것이 무난
Espresso Test Recorder 와 그 경계
※ 이후, https://github.com/googlecodelabs/android-testing 에서 공개된 샘플 앱을 사용한 스크린샷을 게재하고 있습니다
※ build.gradle이 미설정이면 이 순간에 자동 설정 여부가 확인된다.
컴포넌트 | 대응 상황 |
---|---|
TextView | ○ |
EditText | ○ |
Button | ○ |
NavigationDrawer | ○ (전용API는 사용되지 않는다) |
RecyclerView |
△ (전용API는 사용되지 않는다) |
ListView |
△ (onData()가 사용되지 않는다) |
Picker계열 |
△ (spinner계열만 가능) |
WebView내 HTML |
X |
←약 1시간
실천! 변경에 강한 테스트를 효율적으로 적기
샘플 앱에 대해서
즐겨찾기 목록 ↔ Qiita 기사 목록
→→(타이틀 탭으로 상세화면으로)→→ 기사 상세 화면
→→★(CheckBox)탭으로 즐겨찾기 목록에 들어간다
실천! 변경에 강한 테스트를 효율적으로 적기
테스트 자동화 대상의 선정
가능한한
잘하는
테스트 케이스를 자동화 대상으로 한다자동화의 목적에서 벗어나지 않았는가
의 검토는 필요합니다아래의 조건에 맞는 화면
의 테스트를 먼저 자동화한다 (Espresso는 화면 단위로 시험한다)
컴포넌트 | Recorder | 수동 | |
---|---|---|---|
TextView | ○ | ○ | 보다 많이 |
EditText | ○ | ○ | 보다 많이 |
Button | ○ | ○ | 보다 많이 |
NavigationDrawer | ○ | ○ | 보다 많이 |
RecyclerView | △ | △ | 보다 적게 |
ListView | △ | ○ | 보다 적게 |
Picker 계열 | △ | ○ | 보다 적게 |
WebView내 HTML | X | ○ | 보다 적게 |
하고 싶은 것 | Recorder | 수동 | |
---|---|---|---|
표시 텍스트 일치 확인 | ○ | ○ | 보다 많이 |
View의 표시/비표시 확인 | ○ | ○ | 보다 많이 |
그외의 확인 | X | △ | 보다 적게 |
(이미지 일치 확인) | X | X | 대상외 |
View 프로퍼티의 동적인 취득 | X | X | 대상외 |
복잡한 제스쳐 | X | X | 대상외 |
AsyncTask이외의 비동기 대기 | X | △ | 보다 적게 |
즐겨찾기 목록 ↔ Qiita 기사 목록 (O)
→→(타이틀 탭으로 상세화면으로)→→ 기사 상세 화면 (X 별도 프로세스)
→→★(CheckBox)탭으로 즐겨찾기 목록에 들어간다 (△)
(사전에 정하지 않는다)
이 있는지 확인은 불가능
실천! 변경에 강한 테스트를 효율적으로 적기
조작 · 검증 기록
약한
테스트의 전형 사례 (이미지)로그인 화면의 테스트 케이스를 생각한다
"로그인"
이라고 표시된 버튼을 누르면 ~ 되는 것"로그인"
이라고 표시된 버튼을 누르면 ~ 되는 것"로그인"
이라고 표시된 버튼을 누르면 ~ 되는 것Espresso Test Recorder로 평범하게 기록하면 이렇게 된다!
강한
하는 것은? (이미지)같은 조작을 공통부분으로 추출한다
로그인하면
~ 되는 것로그인하면
~ 되는 것로그인하면
~ 되는 것※ 여기에서, “로그인한다” = “로그인”이라고 표시된 버튼을 누른다
나중에 “로그인” 버튼이 “OK” 버튼으로 사양 변경되어도 “※” 만 수정하면 OK
cf. PageObject 디자인 패턴
테스트시에 조작 · 확인할 가능성이 있는 것을 한번만 기록한다
실천! 변경에 강한 테스트를 효율적으로 적기
수정
Help > Find Action으로 입력
Command | Mac | Windows |
---|---|---|
Extract Variable | Cmd+Opt+V | Ctrl+Alt+V |
Extract Method | Cmd+Opt+M | Ctrl+Alt+M |
Inline | Cmd+Opt+N | Ctrl+Alt+N |
Move Line UP | Ctrl+Shift+↑ | Alt+Shift+↑ |
Duplicate Line or Selection | Cmd+D | Ctrl+D |
Generate | Cmd+N | Alt+Insert |
Recorder출력으로 움직이지 않는 항목을 수정한다
(RecyclerView 관련)
Recorder출력으로 움직이지 않는 항목을 수정한다
(RecyclerView 관련)
Recorder출력으로 움직이지 않는 항목을 수정한다
(RecyclerView 관련)
Recorder의 이상한 출력을 수정한다
(RecyclerView 관련)
아래의 메소드를 꺼낸다
(int 인수는 위치)
메소드 | 개요 |
---|---|
goArticleList() | 기사 목록 페이지로 |
goFavsList() | Fav 목록 페이지로 |
toggleFavStatus(int) | Fav 버튼의 토글 |
assertFavStatus (int, boolean) | Fav 버튼 상태 확인 |
assertItemExists(int) | 리스트 아이템 존재 확인 |
assertItemDoesntExist (int) | 리스트 아이템 없는 지 확인 |
조금 전 정의한 메소드만을 사용해
테스트 케이스를 구현한다
대응 방법은 여러 가지 있다
Schedulers.io()만 이용하는 경우는 ③이 좋아 보인다
이번에 소개한 제가 제작한 유틸리티만 빼낸 것을 “Espresso-Commons”으로 공개하고 있습니다.
https://github.com/sumio/espresso-commons
변경에 강한 테스트 코드를 효율 높게 적는 방법을 실연을 포함해서 설명했습니다
한번만
기록한다변경에 강한 테스트 코드를 효율적으로 쓰기에는 마지막으로 실연한 방법에다가 지식과 경험 (경험을 늘리다)
도 중요합니다.
이번에 소개한 기술을 토대로 우선 하나 써보는 것을 추천합니다.
어느 정도 궤도에 오르고 나서 “난이도가 높지만, 효과도 높은 항목”에 도전하는 것을 추천합니다.
comments powered by Disqus
Subscribe to this blog via RSS.
Jetpack Compose: LazyColumn/LazyRow 내부 코드 분석 ~ 2부 LazyList (2) rememberLazyListMeasurePolicy
Posted on 09 Feb 2025Jetpack Compose: LazyColumn/LazyRow 내부 코드 분석 ~ 2부 LazyList (1)
Posted on 25 Jan 2025Jetpack Compose: LazyColumn/LazyRow 내부 코드 분석 ~ 1부 LazyColumn/LazyRow
Posted on 10 Jan 2025