안드로이드 스튜디오 Activity 실행을 위한 Instrumented Unit Testing 하는 방법

 

환경: Android Studio

 

이번에 소개할 것은 안드로이드 스튜디오의 단위 테스트 방법 중 하나인 Instrumented Unit Testing 입니다. 이것은 안드로이드 프레임워크와 별개로 동작하는 Local Unit Test 와 달리 디바이스와 에뮬레이터에서 Activity Service 를 개별 테스트 해 볼 수 있습니다. Instrumented Unit Testing 는 안드로이드 개발 생산성을 위해 반드시 숙지해야 할 기능입니다. 물론 테스트 코드를 추가로 만들어야 하는 개발자들에게는 부담스러운 일이지만 결국 통합 과정에서 해야 될 일입니다. 단위 테스트조차 거치지 않은 코드는 통합 과정에서 어떤 일이 벌어질지 모릅니다. 인력과 시간을 낭비하지 않기 위해서는 중요한 기능들에 대한 테스트 코드는 만들어 두는 것이 좋습니다.  

먼저 Instrumented Unit Testing 환경을 갖추기 위해서는 3가지 라이브러리가 필요합니다. 해당 라이브러리를 다운받기 위해서는 Android Support Repository 라이브러리를 다운 받아야 합니다. Android Testing Support Library 를 포함하고 있기 때문입니다.

 

Support Repository 설치 후에는 app/build.gradle 에 다음 라이브러리를 추가해야 합니다. testIntrumentationRunner Instrumented Unit Testing 을 위한 Runner AndroidJUnitRunner 로 지정하는 것입니다. AndroidJUnitRunner 는 위에서 설치한 Support Repository 에 포함되어 있습니다. 나머지 dependencies 에 있는 것들은 테스트를 위한 라이브러리들 입니다

android {
         ……
    defaultConfig {
         testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
}

dependencies {
    androidTestCompile 'com.android.support:support-annotations:23.1.1'
    androidTestCompile 'com.android.support.test:runner:0.4'
    androidTestCompile 'com.android.support.test:rules:0.4'
}

 

다음은 단위 테스트 파일들이 들어갈 폴더에 Test Artifact 로 지정해 줘야 합니다. 안드로이드 스튜디오는 프로젝트 생성과 함께 기본적으로 두 가지 Test Artifact 옵션 중 Android Instrumented Testing 로 지정되어 있지만 Unit Tests 로 변경 되어 있는 경우 다시 바꿔 줘야 합니다. 화면 좌측 하단에 마우스를 올리면 표시되는 팝업창에서 Build Variants 를 선택합니다

 

Build Variants 창에서 테스트 파일이 들어갈 폴더를 선택하고 Test Artifact Android Instrumentation Tests 를 지정합니다. 폴더가 녹색으로 변경되면 Test Artifact 가 적용된 것입니다

 


이제 환경은 모두 갖춰 졌습니다. 이번에는 Test Code 를 만들어 보겠습니다. 테스트는 Activity 에 있는 TextView 의 값을 가져와서 Log 에 찍는 것입니다. 그러니까 앱을 실행하지 않고도 해당 Activity 만 실행해서 제어가 가능하다는 것이죠. 그림은 Activity를 실행한 모습입니다. 단위 테스트를 실행해서 Hello 값을 가져와 보겠습니다

 

화면을 구성하는 Activity Layout 소스는 다음과 같습니다. 단위 테스트 함수에서는 id/textview 에 있는 text=”Hello” 를 가져와서 로그에 찍을 예정입니다. 

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class MovieActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_movie);

        TextView tv = (TextView)findViewById(R.id.textView);
    }
}


R.layout.activity_movie


<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.gon.rstpclient.MovieActivity" android:weightSum="1"> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="New Button" android:id="@+id/button2" /> <TextView android:layout_width="70dp" android:layout_height="wrap_content" android:text="Hello" android:id="@+id/textView" android:layout_gravity="center_horizontal"/> </LinearLayout>


다음은 단위 테스트 실행 파일입니다. ActivityInstrumentationTestCase2 클래스를 상속 받아야 합니다. ActivityInstrumentationTestCase2 는 JUnit 과 Instrumentation 을 상속 받습니다. Instrumentation 에는 안드로이드 시스템에서 제어하는 메소드 호출과 이벤트 등을 바꾸거나 가로채 제어할 수 있는 함수들이 들어가 있습니다. 생명주기도 Instrumentation 에서 관리할 수 있는데 activity.finish() 를 호출하면 Activity 는 Destory 됩니다. ActivityInstrumentationTestCase2 의 제너릭에는 실행할 Activity 클래스가 들어가야 합니다. 그리고 생성자 함수에도 super(MovieActivity.class); 와 같이 Activity 클래스를 넘깁니다. 

import android.test.ActivityInstrumentationTestCase2;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;
import android.widget.TextView;

public class MovieActivityTest extends ActivityInstrumentationTestCase2<MovieActivity> {
    private MovieActivity activity;

    public MovieActivityTest() {
        super(MovieActivity.class);
    }

    @Override
    protected void setUp() throws Exception{
        super.setUp();
        activity = getActivity();
    }

    @SmallTest
    public void testTextView(){
        TextView tv = (TextView)activity.findViewById(R.id.textView);
        String txt = (String) tv.getText();

        Log.d(this.getClass().getName(), txt);
    }
}


testTextView() 에서 실행한 함수의 결과는 다음과 같습니다. setup() 에서 생성한 Activity 객체를 이용해서 TextView 를 접근합니다. 그리고 getText() 함수를 사용해서 값을 가져오는 것입니다. 결과는 Logcat 에서 확인할 수 있습니다. 


Posted by 녹두장군

댓글을 달아 주세요