Android에서 앱 테스트 (Test apps on Android)
Android/Android Test

Android에서 앱 테스트 (Test apps on Android)

728x90
반응형

테스트 기본 요소(Fundamentals of Testing)

사용자는 버튼을 누르는 것부터 기기에 정보를 다운로드하는 것에 이르기까지 다양한 수준에서 앱과 상호작용합니다. 따라서 반복적으로 앱을 개발할 때 다양한 사용 사례와 상호작용을 테스트해야 합니다.

앱이 확장됨에 따라 서버에서 데이터를 가져오거나, 기기 센서와 상호작용하거나, 로컬 저장소에 액세스하거나, 복잡한 사용자 인터페이스를 렌더링해야 할 수 있습니다. 앱 다양성을 고려하여 종합적인 테스트 전략을 수립해야 합니다.

반복적으로 코드 만들기 및 테스트
새 기능을 디자인할 때 나타나는 책임 단위를 고려하는 것이 중요합니다. 단위마다 해당하는 단위 테스트를 작성합니다. 단위 테스트는 표준 상호작용, 잘못된 입력, 사용 가능한 리소스가 없는 사례를 비롯한 단위와의 가능한 모든 상호작용을 다뤄야 합니다.  (Jetpack 라이브러리 사용 추천)

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

 

효과적인 단위 테스트 빌드(Build effective unit tests)

 

 

 

사용자 인터페이스 테스트 자동화(Automate user interface tests)

 

 

 

앱 구성요소 통합 테스트(Test app component integrations)

  • Service
  • Contents provider

 

UI 성능 테스트(Test UI performance)

 

 

 

구글 공식 테스팅 샘플코드 깃주소

github.com/android/testing-samples

 

android/testing-samples

A collection of samples demonstrating different frameworks and techniques for automated testing - android/testing-samples

github.com


Espresso

 

 

kotlin

@Test
fun greeterSaysHello() {
    onView(withId(R.id.name_field)).perform(typeText("Steve"))
    onView(withId(R.id.greet_button)).perform(click())
    onView(withText("Hello Steve!")).check(matches(isDisplayed()))
}

java

@Test
public void greeterSaysHello() {
    onView(withId(R.id.name_field)).perform(typeText("Steve"));
    onView(withId(R.id.greet_button)).perform(click());
    onView(withText("Hello Steve!")).check(matches(isDisplayed()));
}

 


UI Automator

kotlin

device = UiDevice.getInstance(getInstrumentation())
device.pressHome()

// Bring up the default launcher by searching for a UI component
// that matches the content description for the launcher button.
val allAppsButton: UIObject = device.findObject(
        UiSelector().description("Apps"))

// Perform a click on the button to load the launcher.
allAppsButton.clickAndWaitForNewWindow()

java

device = UiDevice.getInstance(getInstrumentation());
device.pressHome();

// Bring up the default launcher by searching for a UI component
// that matches the content description for the launcher button.
UiObject allAppsButton = device
        .findObject(new UiSelector().description("Apps"));

// Perform a click on the button to load the launcher.
allAppsButton.clickAndWaitForNewWindow();

 


AndroidX 테스트 에서 JUnit4 rules 적용 

ActivityTestRule

ActivityScenarioRule 적용

kotlin

@RunWith(AndroidJUnit4::class.java)
@LargeTest
class MyClassTest {
    @get:Rule
    val activityRule = ActivityScenarioRule(MyClass::class.java)

    @Test fun myClassMethod_ReturnsTrue() { ... }
}

java

@RunWith(AndroidJUnit4.class)
@LargeTest
public class MyClassTest {
    @Rule
    public ActivityScenarioRule<MyClass> activityRule =
            new ActivityScenarioRule(MyClass.class);

    @Test
    public void myClassMethod_ReturnsTrue() { ... }
}

ServiceTestRule

kotlin

@RunWith(AndroidJUnit4::class.java)
@MediumTest
class MyServiceTest {
    @get:Rule
    val serviceRule = ServiceTestRule()

    @Test fun testWithStartedService() {
        serviceRule.startService(
            Intent(ApplicationProvider.getApplicationContext<Context>(),
            MyService::class.java))

        // Add your test code here.
    }

    @Test fun testWithBoundService() {
        val binder = serviceRule.bindService(
            Intent(ApplicationProvider.getApplicationContext(),
            MyService::class.java))
        val service = (binder as MyService.LocalBinder).service
        assertThat(service.doSomethingToReturnTrue()).isTrue()
    }
}

java

@RunWith(AndroidJUnit4.class)
@MediumTest
public class MyServiceTest {
    @Rule
    public final ServiceTestRule serviceRule = new ServiceTestRule();

    @Test
    public void testWithStartedService() {
        serviceRule.startService(
                new Intent(ApplicationProvider.getApplicationContext(),
                MyService.class));
        // Add your test code here.
    }

    @Test
    public void testWithBoundService() {
        IBinder binder = serviceRule.bindService(
                new Intent(ApplicationProvider.getApplicationContext(),
                MyService.class));
        MyService service = ((MyService.LocalBinder) binder).getService();
        assertThat(service.doSomethingToReturnTrue()).isTrue();
    }
}

AndroidJUnitRunner

Write JUnit tests

kotlin

@RunWith(AndroidJUnit4::class)
@LargeTest
class ChangeTextBehaviorTest {
    val stringToBeTyped = "Espresso"
    @get:Rule
    val activityRule = ActivityTestRule(MainActivity::class.java)

    @Test fun changeText_sameActivity() {
        // Type text and then press the button.
        onView(withId(R.id.editTextUserInput))
            .perform(typeText(stringToBeTyped), closeSoftKeyboard())
        onView(withId(R.id.changeTextBt)).perform(click())

        // Check that the text was changed.
        onView(withId(R.id.textToBeChanged))
            .check(matches(withText(stringToBeTyped)))
    }
}

java

@RunWith(AndroidJUnit4.class)
@LargeTest
public class ChangeTextBehaviorTest {

    private static final String stringToBeTyped = "Espresso";

    @Rule
    public ActivityTestRule<MainActivity> activityRule =
            new ActivityTestRule<>(MainActivity.class);

    @Test
    public void changeText_sameActivity() {
        // Type text and then press the button.
        onView(withId(R.id.editTextUserInput))
                .perform(typeText(stringToBeTyped), closeSoftKeyboard());
        onView(withId(R.id.changeTextBt)).perform(click());

        // Check that the text was changed.
        onView(withId(R.id.textToBeChanged))
                .check(matches(withText(stringToBeTyped)));
    }
}

Android Test Orchestrator 사용

 

장점

  • Minimal shared state(최소 공유 상태) : 각 테스트는 자체 Instrumentation 인스턴스에서 실행됩니다. 따라서 테스트가 앱 상태를 공유하는 경우 각 테스트 후 이러한 공유 상태 대부분이 기기의 CPU 또는 메모리에서 삭제됩니다.
  • Crashes are isolated(비정상 종료 각리됨) : 테스트 하나가 비정상 종료되더라도 자체 Instrumentation 인스턴스만 삭제하므로 모음에 있는 나머지 테스트는 계속 실행됩니다.



각 테스트 후 모든 공유 상태를 기기의 CPU와 메모리에서 삭제하려면 clearPackageData 플래그를 사용하세요.

Mockito

 

 

 

 

 

 

 

 

 

 

 

 

 

 

참고

안드로이드 Developer 공식 사이트 developer.android.com/training/testing?hl=ko

728x90
반응형