안 드 로 이 드 유닛 테스트 최 적 실천 상세 설명

목적.
충분 한 유닛 테스트 는 코드 품질 을 향상 시 키 는 가장 효과 적 인 수단 중 하나 이다.유닛 테스트 는 코드 의 테스트 가능성 에 심각하게 의존한다.본 고 는 주로 간단 한 DEMO 를 통 해 안 드 로 이 드 네 이 티 브 응용 에 대해 유닛 테스트 를 하 는 방법 을 보 여 주 는 동시에 예제 코드 는 MVP 모델 로 코드 의 가 독성 과 테스트 가능성 을 높 인 다.
간단 한 소개
Android 네 이 티 브 애플 리 케 이 션 개발 에는 로 컬 JVM 테스트 와 Instrumentation 테스트 두 가지 유닛 테스트 가 존재 합 니 다.본 고 는 로 컬 JVM 테스트 만 소개 합 니 다.
로 컬 jvm 단위 테스트
이런 방식 은 운행 속도 가 빠 르 고 운행 환경 에 대해 특별한 요구 가 없 으 며 자동화 테스트 를 편리 하 게 할 수 있 으 며 단원 테스트 에서 가장 선 호 하 는 방법 이다.
계측 테스트
Instrumentation 테스트 는 Android 환경 에서 실행 되 어야 하 며 시 뮬 레이 터 나 휴대 전화 등 실제 장치 일 수 있 습 니 다.이런 방식 은 운행 속도 가 느 리 고 안 드 로 이 드 운행 환경 에 심각하게 의존 하여 통합 테스트 에 더욱 적합 하 다.
준비 하 다.
저 는 간단 한 앱 을 준 비 했 습 니 다.시간 이 걸 리 는 네트워크 요청 을 모 의 하여 데 이 터 를 얻 고 인터페이스 에 표시 합 니 다.이 앱 에 대해 유닛 테스트 사례 를 작성 하고 로 컬 유닛 테스트 를 실시 합 니 다.

앱 실행 효과
의존 라 이브 러 리
의존 라 이브 러 리
역할.
JUnit-4.12
기초 유닛 테스트 프레임 워 크
Robolectric-3.8
Android SDK 테스트 프레임 워 크
PowerMock-1.6.6
테스트 대상 이 의존 하 는 정적 방법 을 모 의 합 니 다.
Mockito-1.10.19
테스트 대상 의존 대상 시 뮬 레이 션
build.gradle 설정
컴 파일 옵션 을 추가 하여 테스트 에 자원 파일 을 포함 합 니 다.

 testOptions {
  unitTests {
   includeAndroidResources true
  }
 }
테스트 의존 라 이브 러 리 추가

 testImplementation 'junit:junit:4.12'
 testImplementation 'org.robolectric:robolectric:3.8'
 testImplementation 'org.robolectric:shadows-supportv4:3.8'
 testImplementation 'org.powermock:powermock-module-junit4:1.6.6'
 testImplementation 'org.powermock:powermock-module-junit4-rule:1.6.6'
 testImplementation 'org.powermock:powermock-api-mockito:1.6.6'
 testImplementation 'org.powermock:powermock-classloading-xstream:1.6.6'
 testImplementation 'org.mockito:mockito-all:1.10.19'
테스트 활동
테스트 Activity 는 주로 각 라 이 프 사이클 의 상태 변화,외부 입력 에 대한 응답 이 기대 에 부합 하 는 지 테스트 하 는 것 입 니 다.Activity 테스트 는 완전히 Android SDK 에 의존 하기 때문에 Robolectric 을 사용 해 야 합 니 다.
Robolectric 은 Android SDK 를 완전히 모 의 하고 JVM 에서 실행 할 수 있 는 오픈 소스 유닛 테스트 프레임 워 크 입 니 다.
UI 는 Persenter 에 의존 합 니 다.Activity 에서 정적 공장 방법 으로 의존 하 는 Presenter 인 스 턴 스 를 만 들 려 면 PowerMock 을 사용 하여 Presenter 생 성 과정 을 모 의 하고 Presenter 시 뮬 레이 션 대상 의 주입 을 완성 해 야 합 니 다.
배치 하 다.
  • @RunWith 지정 을 통 해 RobolectricTestRunner 를 사용 합 니 다
  • @Config 를 통 해 Robolectric 의 운영 환경 을 설정 합 니 다
  • @prepareForTest 를 통 해 PowerMock 이 시 뮬 레이 션 해 야 할 정적 유형 을 설정 합 니 다
  • 
    @RunWith(RobolectricTestRunner.class)
    @Config(sdk = 21, constants = BuildConfig.class)
    @PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*"})
    @PrepareForTest({PresenterFactory.class})
    
     @Before
     public void setUp() {
      appContext = RuntimeEnvironment.application.getApplicationContext();
      PowerMockito.mockStatic(PresenterFactory.class);
     }
    onCreate 용례
    Robolectric 의 Activity Controller 를 통 해 activity 의 생명 주 기 를 구축 하고 관리 하 며 onCreate 단계 로 실행 한 다음 이 단계 text 1 이 올 바 르 게 초기 화 되 었 는 지 검증 합 니 다.
    
     @Test
     public void onCreate_text1() {
      MainActivity activity = Robolectric.buildActivity(MainActivity.class).create().get();
      String expect = appContext.getString(R.string.hell_world);
      assertEquals(expect, ((TextView)activity.findViewById(R.id.lbl_text1)).getText());
     }
    버튼 1 예 를 클릭 합 니 다
    Activity 가 완전히 표 시 된 후 button 1 의 click 작업 이 toast 메 시 지 를 표시 하 는 지 확인 합 니 다.
    
     @Test
     public void btn1_click() {
      MainActivity activity = Robolectric.setupActivity(MainActivity.class);
      activity.findViewById(R.id.btn_1).performClick();
      String expect = appContext.getString(R.string.hell_world);
      assertEquals(expect, ShadowToast.getTextOfLatestToast());
     }
    
    버튼 2 예 를 클릭 합 니 다
    Activity 가 완전히 표 시 된 후,button 2 의 click 작업 이 presenter 의 fetch 방법 을 호출 했 는 지 검증 합 니 다.
    
     @Test
     public void btn2_click() {
      MainContract.Presenter presenter = Mockito.mock(MainContract.Presenter.class);
      PowerMockito.when(PresenterFactory.create(Mockito.any(MainContract.View.class), Mockito.any(AppExecutors.class)))
        .thenReturn(presenter);
    
      MainActivity activity = Robolectric.setupActivity(MainActivity.class);
    
      activity.findViewById(R.id.btn_2).performClick();
    
      Mockito.verify(presenter, Mockito.times(1))
        .fetch();
     }
    
    테스트 발표 자
    Presenter 의 테스트 는 일반적으로 Android SDK 에 의존 하지 않 아 도 됩 니 다.Presenter 는 바 텀 분야 의 서비스 에 의존 하고 상층 View 에 도 의존 합 니 다.demo 에서 분야 서비스 에 대한 의존 은 구조 함수 방식 으로 주입 되 지 않 고 정적 공장 방법 으로 구축 되 어야 합 니까?아니면 PowerMock 을 사용 해 야 합 니까?
    배치 하 다.
  • @RunWith 지정 을 통 해 PowerMockRunner 를 사용 합 니 다
  • @prepareForTest 를 통 해 PowerMock 이 시 뮬 레이 션 해 야 할 정적 유형 을 설정 합 니 다
  • 
    @RunWith(PowerMockRunner.class)
    @PrepareForTest({ServiceFactory.class})
    
    
     @Before
     public void setUp() {
      PowerMockito.mockStatic(ServiceFactory.class);
     }
    
    성공 경로 용례
    View 방법 이 성공 적 으로 호출 되 었 는 지,호출 매개 변수 가 일치 하 는 지 검증 합 니 다.
    
     @Test
     public void fetch_success() {
      String expected = "hello world";
      SlowService service = Mockito.mock(SlowService.class);
      Mockito.when(service.fetch()).thenReturn(expected);
      PowerMockito.when(ServiceFactory.create())
        .thenReturn(service);
    
      MainContract.View view = Mockito.mock(MainContract.View.class);
      MainPresenter presenter = new MainPresenter(view, executors);
    
      presenter.fetch();
    
      Mockito.verify(service, Mockito.times(1)).fetch();
      Mockito.verify(view, Mockito.times(1)).onFetchStarted();
      Mockito.verify(view, Mockito.times(1)).onFetchCompleted();
      Mockito.verify(view, Mockito.times(0)).onFetchFailed(Mockito.anyObject());
      ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
      Mockito.verify(view, Mockito.times(1)).onFetchSuccess(captor.capture());
      assertEquals(expected, captor.getValue());
     }
    
    
    실패 경로 예
    
     @Test
     public void fetch_failed() {
      RuntimeException exception = new RuntimeException("fetch failed");
    
      SlowService service = Mockito.mock(SlowService.class);
      Mockito.when(service.fetch()).thenThrow(exception);
      PowerMockito.when(ServiceFactory.create())
        .thenReturn(service);
    
      MainContract.View view = Mockito.mock(MainContract.View.class);
      MainPresenter presenter = new MainPresenter(view, executors);
    
      presenter.fetch();
    
      Mockito.verify(service, Mockito.times(1)).fetch();
      Mockito.verify(view, Mockito.times(1)).onFetchStarted();
      Mockito.verify(view, Mockito.times(1)).onFetchCompleted();
      ArgumentCaptor<Throwable> captor = ArgumentCaptor.forClass(Throwable.class);
      Mockito.verify(view, Mockito.times(1)).onFetchFailed(captor.capture());
      assertEquals(exception, captor.getValue());
      Mockito.verify(view, Mockito.times(0)).onFetchSuccess(Mockito.anyString());
     }
    
    
    테스트 서비스
    Service 는 상부 에 의존 하지 않 고 JUnit 테스트 를 직접 사용 할 수 있 습 니 다.
    
    public class SlowServiceImplTest {
    
     @Test
     public void fetch_data() {
      SlowServiceImpl impl = new SlowServiceImpl();
      String data = impl.fetch();
      assertEquals("from slow service", data);
     }
    
    }
    
    
    자동화 테스트
    자동화 테스트 는 일반적으로 지속 적 인 집적 환경 에서 명령 을 사용 하여 단원 테스트 를 집행 한다
    
    gradlew :app:testDebugUnitTest
    총결산
    이 demo 를 쓰 고 나 면 Android APP 에 유닛 테스트 를 하 는 것 이 매우 간단 하 다 고 생각 합 니 다.우수한 프로그래머 로 서 어떻게 자신의 코드 품질 에 관심 을 가지 지 않 을 수 있 습 니까?직접 해 보 세 요.
    원본 코드 다운로드
    https://github.com/hziee514/android-testing
    참고 자료
    Robolectric
    Using PowerMock
    Mockito
    이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

    좋은 웹페이지 즐겨찾기