테크바일개발그룹                                                  Android Unit Testing                                            ...
테크바일개발그룹1.   관련 자료 및 용어 정의Android Unit Testing 과 관련된 자료는 다음과 같은 곳에서 얻을 수 있다.        Testing Fundamentals: 전반적인 개념에 대한 공식 ...
테크바일개발그룹           는 것이다. 따라서 검증 프로그램 구현시 사용자 시나리오를 검증하려고 시도           하지 말고, 해당 유닛의 독립적인 검증을 자바 클래스 단위로 진행하는 것이          ...
테크바일개발그룹2.   안드로이드테스트 프로젝트 만들기관련 자료들의 내용에 준하여, 이클립스 상에서 기 개발된 "SimpleGroupBell"을ApplicationUnder Test 로 다음과 같이 안드로이드테스트 프로...
테크바일개발그룹여기까지 진행하면 다음과 같이 manifest file이 생성된다. 아직 소스는 생성되지 않은 상태이다.<SimpleGroupBellTestsAndroidManifest.xml><manifest     p...
테크바일개발그룹상기 화면캡처와 유사한 방식으로 테스트 패키지에 두개의 테스트 클래스를 추가한 예제 코드는 다음과 같다.<SimpleGroupBellTestssrccomperceiv2SimpleGroupBelltestTe...
테크바일개발그룹ActivityInstrumentationTestCase2<SimpleGroupBellActivity> {private SimpleGroupBellActivitymActivity;      // 이 con...
테크바일개발그룹public class TestSuiteAccountTypeInfo extends AndroidTestCase {@Smokepublic void testCase1() {assertTrue(true);}@S...
테크바일개발그룹      9/19
테크바일개발그룹3.   안드로이드 테스트 케이스 만들기 (Android Open Source 상의 예제들)전 장에서 안드로이드 테스트 프로젝트를 구성해 보았으므로, 남은 일은 각각의 test case를구현할 때 복잡한 ...
테크바일개발그룹             인하고 있지 않으며, 단지 test activity의 유무만 확인하고 있다.<packagesappsSettingstestssrccomandroidsettingsSettingsHook...
테크바일개발그룹         }assertTrue("Intent-filter not found", result);    }}        com.android.calculator2.tests             ...
테크바일개발그룹assertEquals(displayVal(), "189");         // make sure we can continue calculations also         // 189 - 789 => ...
테크바일개발그룹     public void testTheOrderOfGetImageAt() {MockImageListlistA = new MockImageList();MockImageListlistB = new Moc...
테크바일개발그룹4.     Test Coverage4.1.    Test Coverage란?<http://en.wikipedia.org/wiki/Software_testing>Techniques used in white...
테크바일개발그룹for our system is not good at helping us find bugs of omission, that is to say bugs were simplyleft out of somethi...
테크바일개발그룹4.3.   ANT cmdline빌드를 위한 build.xml 만들기<http://blackriverweb.com/2012/02/android-continuous-integration-with-ant-an...
테크바일개발그룹ant all clean은 all에서 에러가 나서 all 삭제하고 실행함결과물 분석 필요!아래 두 url에서 coverage 결과물 경로 확인하자.<http://blackriverweb.com/2012/0...
테크바일개발그룹<http://developer.android.com/tools/building/building-cmdline.html>ant emma debug install testBuilds a test projec...
Upcoming SlideShare
Loading in …5
×

Android unit testing

1,136 views

Published on

Incomplete document for upload testing...

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
1,136
On SlideShare
0
From Embeds
0
Number of Embeds
6
Actions
Shares
0
Downloads
15
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Android unit testing

  1. 1. 테크바일개발그룹 Android Unit Testing 1판: 2012년 10월 30일테크바일 장형규 목차1. 관련 자료 및 용어 정의 ....................................................................................................... 22. 안드로이드 테스트 프로젝트 만들기 ................................................................................... 43. 안드로이드 테스트 케이스 만들기 (Android Open Source 상의 예제들) ........................ 104. Test Coverage ..................................................................................................................... 15 4.1. Test Coverage란? ................................................................................................ 15 4.2. ANT 설치하기 ...................................................................................................... 16 4.3. ANT 로 빌드하기 ................................................................................................. 17 1/19
  2. 2. 테크바일개발그룹1. 관련 자료 및 용어 정의Android Unit Testing 과 관련된 자료는 다음과 같은 곳에서 얻을 수 있다.  Testing Fundamentals: 전반적인 개념에 대한 공식 사이트  http://developer.android.com/tools/testing/testing_android.html  Activity Testing Tutorial: 예제 프로그램에 대한 공식 사이트  http://developer.android.com/tools/testing/activity_test.html  Testing on android: JUnit을 포함하는 발표자료  https://docs.google.com/viewer?a=v&pid=sites&srcid=Y29kdGVjaC5jb218YW5kc m9pZHxneDo1MjA5MGNjY2YwMTFjZDYz관련 자료들은 기본 개념과 기본 예제를 다루고 있으나, 이를 숙지한 후에 실제로 다양한작업을 하기에 필요한 고급 예제나 문서는 공식 사이트의 reference를 제외하고는 찾기가어려웠다. 이에 본 문서에서는 이를 보완할 수 있는 내용을 다루는 것을 주 목적으로 한다.기본적인 용어 정의에는 "http://en.wikipedia.org/wiki/Software_testing"를 기준으로 다음과 같은 것들이 있다.  Unit testing  Unit testing, also known as component testing, refers to tests that verify the functionality of a specific section of code, usually at the function level. In an object- oriented environment, this is usually at the class level, and the minimal unit tests include the constructors and destructors.  These types of tests are usually written by developers as they work on code (white-box style), to ensure that the specific function is working as expected. One function might have multiple tests, to catch corner cases or other branches in the code. Unit testing alone cannot verify the functionality of a piece of software, but rather is used to assure that the building blocks the software uses work independently of each other.  이상의 정의에 따르면 유닛 검증은 시스템 통합 및 검증의 전단계에서 이루어 지는 것으로 일련의 시나리오를 검증하는 것이 목적이 아니라, 해당 유닛이 연 동에 필요한 인터페이스를 만족하도록 구현되었는지를 소스를 기준으로 확인하 2/19
  3. 3. 테크바일개발그룹 는 것이다. 따라서 검증 프로그램 구현시 사용자 시나리오를 검증하려고 시도 하지 말고, 해당 유닛의 독립적인 검증을 자바 클래스 단위로 진행하는 것이 좋을 것이다.  Test case  A test case normally consists of a unique identifier, requirement references from a design specification, preconditions, events, a series of steps (also known as actions) to follow, input, output, expected result, and actual result. Clinically defined a test case is an input and an expected result. This can be as pragmatic as for condition x your derived result is y, whereas other test cases described in more detail the input scenario and what results might be expected. It can occasionally be a series of steps (but often steps are contained in a separate test procedure that can be exercised against multiple test cases, as a matter of economy) but with one expected result or expected outcome. The optional fields are a test case ID, test step, or order of execution number, related requirement(s), depth, test category, author, and check boxes for whether the test is automatable and has been automated. Larger test cases may also contain prerequisite states or steps, and descriptions. A test case should also contain a place for the actual result. These steps can be stored in a word processor document, spreadsheet, database, or other common repository. In a database system, you may also be able to see past test results, who generated the results, and what system configuration was used to generate those results. These past results would usually be stored in a separate table.  Test suite  The most common term for a collection of test cases is a test suite. The test suite often also contains more detailed instructions or goals for each collection of test cases. It definitely contains a section where the tester identifies the system configuration used during testing. A group of test cases may also contain prerequisite states or steps, and descriptions of the following tests.즉 Android Unit Testing은 자바 코드를 통해 어플리케이션 모듈을 시험하기 위해 test suite의 의미로 그룹되어진 test class 들을 만드는 것이다. 각 test class는 test case에 해당하는test method들을 포함한다. 각 test method는 어플리케이션의 각 method를 독립적으로 시험하는 것일 수도 있고 일련의 시나리오를 (전체 시스템이 아닌 유닛 내부에서의 시나리오)시험하는 것일 수도 있다. 3/19
  4. 4. 테크바일개발그룹2. 안드로이드테스트 프로젝트 만들기관련 자료들의 내용에 준하여, 이클립스 상에서 기 개발된 "SimpleGroupBell"을ApplicationUnder Test 로 다음과 같이 안드로이드테스트 프로젝트를 만들어 보기로 한다. 단"E:AndroidEclipseWorkspaceSimpleGroupBell" 아래에 "tests" 폴더를 만들고 여기에 테스트프로젝트를 생성하려고 하였으나 잘 되지 않아,"E:AndroidEclipseWorkspaceSimpleGroupBellTests"로 생성하기로 한다. 4/19
  5. 5. 테크바일개발그룹여기까지 진행하면 다음과 같이 manifest file이 생성된다. 아직 소스는 생성되지 않은 상태이다.<SimpleGroupBellTestsAndroidManifest.xml><manifest package="com.perceiv2.SimpleGroupBell.test"<instrumentationandroid:name="android.test.InstrumentationTestRunner"android:targetPackage="com.perceiv2.SimpleGroupBell" /><application><uses-library android:name="android.test.runner" /></application></manifest>소스를 추가하기 위하여 다음과 같은 동작을 한다. 5/19
  6. 6. 테크바일개발그룹상기 화면캡처와 유사한 방식으로 테스트 패키지에 두개의 테스트 클래스를 추가한 예제 코드는 다음과 같다.<SimpleGroupBellTestssrccomperceiv2SimpleGroupBelltestTestSuiteMainActivity.java>// 패키지명 뒤 부분의 ".test"를 생략하면 AndroidManifest.xml과 정의가 상이하여// 오류가 발생함.package com.perceiv2.SimpleGroupBell.test;import android.test.ActivityInstrumentationTestCase2;// @Test는 JUnit4에서 사용되는 annotation인데, import org.junit.Test와 @Test를// 사용할 경우 컴파일은 가능하나 실행시NoClassDefFoundError 오류가 발생함.// suitebuilder.annotation에 있는 annotation만 사용해야 할 것으로 보이는데,// @SmallTest, @Smoke는 grouping을 위한 단순 tag로 Test Case로 인식되는 것은// 이름이 "test"로 시작하는 함수이고 annotation과는 무관하다importandroid.test.suitebuilder.annotation.*;import com.perceiv2.SimpleGroupBell.SimpleGroupBellActivity;public class TestSuiteMainActivity extends 6/19
  7. 7. 테크바일개발그룹ActivityInstrumentationTestCase2<SimpleGroupBellActivity> {private SimpleGroupBellActivitymActivity; // 이 constructor를 생략할 경우 컴파일 오류가 발생한다.public TestSuiteMainActivity() {// ActivityInstrumentationTestCase2(String pkg, Class<T>activityClass)// : This constructor is deprecated. // : use ActivityInstrumentationTestCase2(Class) insteadsuper(/*"com.perceiv2.SimpleGroupBell",*/ SimpleGroupBellActivity.class);}@Overrideprotected void setUp() throws Exception {super.setUp();setActivityInitialTouchMode(false);mActivity = getActivity();}@Smokepublic void testCase1() {assertTrue(mActivity != null);}@SmallTestpublic void testCase2() {assertTrue(mActivity == null);}public void testCase3() {assertTrue(mActivity != null);}public void noTestCase1() {assertTrue(mActivity != null);}public void TestCaseNo2() {assertTrue(mActivity != null);}}<SimpleGroupBellTestssrccomperceiv2SimpleGroupBelltestTestSuiteAccountTypeInfo.java>package com.perceiv2.SimpleGroupBell.test;import android.test.AndroidTestCase;import android.test.suitebuilder.annotation.SmallTest;import android.test.suitebuilder.annotation.Smoke; 7/19
  8. 8. 테크바일개발그룹public class TestSuiteAccountTypeInfo extends AndroidTestCase {@Smokepublic void testCase1() {assertTrue(true);}@SmallTestpublic void testCase2() {assertTrue(false);}public void testCase3() {//assertTrue(true);}public void noTestCase1() {assertTrue(true);}public void TestCaseNo2() {assertTrue(true);}}상기 테스트 프로젝트를 실행하면 다음과 같은 결과를 얻을 수 있다. 8/19
  9. 9. 테크바일개발그룹 9/19
  10. 10. 테크바일개발그룹3. 안드로이드 테스트 케이스 만들기 (Android Open Source 상의 예제들)전 장에서 안드로이드 테스트 프로젝트를 구성해 보았으므로, 남은 일은 각각의 test case를구현할 때 복잡한 test case를 만드는 예제들을 검토하는 것인데, source.android.com 에서Android Open Source를 구해 "packagesapps...tests" 에 있는 예제들을 검토할 수 있다.어플리케이션 이외에 서비스나 provider에 대한 예제도 검토할 수 있으나, 본 문서에서는android-4.0.4_r2.1를 기준으로 어플리케이션 테스트 예제들을 우선 검토하기로 한다.검토중 테스트 클래스의 패키지명에 ".test"의 suffix가 붙어 있는 경우가 없어 이에 대해 확인하고자 하였으나 suffix가 없는 이유를 알아내지 못하였다. 따라서 이 문제는 유보하기로한다.  com.android.settings.tests  Settings class에 대한 시험은 해당 유닛에 대한 기능이나 method를 특별히 확 10/19
  11. 11. 테크바일개발그룹 인하고 있지 않으며, 단지 test activity의 유무만 확인하고 있다.<packagesappsSettingstestssrccomandroidsettingsSettingsHookTests.java>public class SettingsHookTests extends ActivityInstrumentationTestCase2<Settings> {/** * Test that the operator/manufacturer settings hook test application is * available and that its installed in the devices system image. */ public void testSettingsHookTestAppAvailable() throws Exception { Context context = mSettings.getApplicationContext();PackageManager pm = context.getPackageManager();ApplicationInfoapplicationInfo = pm.getApplicationInfo(PACKAGE_NAME, 0);assertTrue((applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0); } /** * Test that the operator test activity has registered an intent-filter for * an action named android.settings.OPERATOR_APPLICATION_SETTING. */ public void testOperatorIntentFilter() {boolean result = false; Context context = mSettings.getApplicationContext();PackageManager pm = context.getPackageManager(); Intent intent = new Intent(INTENT_OPERATOR_HOOK); List<ResolveInfo> list = pm.queryIntentActivities(intent, 0); for (ResolveInforesolveInfo : list) { if (resolveInfo.activityInfo.packageName.equals(PACKAGE_NAME)) { result = true; } }assertTrue("Intent-filter not found", result); } /** * Test that the manufacturer test activity has registered an intent-filter * for an action named android.settings.MANUFACTURER_APPLICATION_SETTING. */ public void testManufacturerIntentFilter() {boolean result = false; Context context = mSettings.getApplicationContext();PackageManager pm = context.getPackageManager(); Intent intent = new Intent(INTENT_MANUFACTURER_HOOK); List<ResolveInfo> list = pm.queryIntentActivities(intent, 0); for (ResolveInforesolveInfo : list) { if (resolveInfo.activityInfo.packageName.equals(PACKAGE_NAME)) { result = true; } 11/19
  12. 12. 테크바일개발그룹 }assertTrue("Intent-filter not found", result); }}  com.android.calculator2.tests  Calculator class에 대한 시험은 key 입력과 터치 입력 두가지에 대해 각각 한 가지 기본적인 수식으로 결과를 확인하고 있다.<packagesappsCalculatortestssrccomandroidcalculator2CalculatorHitSomeButtons.java>public class CalculatorHitSomeButtons extends ActivityInstrumentationTestCase<Calculator>{ @LargeTest public void testPressSomeKeys() {Log.v(TAG, "Pressing some keys!"); // Make sure that we clear the output press(KeyEvent.KEYCODE_ENTER); press(KeyEvent.KEYCODE_CLEAR); // 3 + 4 * 5 => 23 press(KeyEvent.KEYCODE_3); press(KeyEvent.KEYCODE_PLUS); press(KeyEvent.KEYCODE_4); press(KeyEvent.KEYCODE_9 | KeyEvent.META_SHIFT_ON); press(KeyEvent.KEYCODE_5); press(KeyEvent.KEYCODE_ENTER);assertEquals(displayVal(), "23"); } @LargeTest public void testTapSomeButtons() {Log.v(TAG, "Tapping some buttons!"); // Make sure that we clear the output tap(R.id.equal); tap(R.id.del); // 567 / 3 => 189 tap(R.id.digit5); tap(R.id.digit6); tap(R.id.digit7); tap(R.id.div); tap(R.id.digit3); tap(R.id.equal); 12/19
  13. 13. 테크바일개발그룹assertEquals(displayVal(), "189"); // make sure we can continue calculations also // 189 - 789 => -600 tap(R.id.minus); tap(R.id.digit7); tap(R.id.digit8); tap(R.id.digit9); tap(R.id.equal); // Careful: the first digit in the expected value is u2212, not "-" (a hyphen)assertEquals(displayVal(), mActivity.getString(R.string.minus) + "600"); }}  com.android.contacts.tests  Contact의 경우 상당히 많은 test class들이 존재하므로 임의로 한개를 골라 내 용을 확인해 본다.<packagesappsContactstestssrccomandroidcontactslistContactListItemViewTest.java>/** * Unit tests for {@link ContactListItemView}.*/public class ContactListItemViewTest extendsActivityInstrumentationTestCase2<PeopleActivity> {public void testShowDisplayName_Simple() { Cursor cursor = createCursor("John Doe", "Doe John");ContactListItemView view = createView();view.showDisplayName(cursor, 0,ContactsContract.Preferences.DISPLAY_ORDER_PRIMARY);SpannedTestUtils.checkHtmlText("John Doe", view.getNameTextView()); }}  갤러리: com.android.camera.tests  갤러리의 경우 많은 테스트가 있는 것은 아니지만, 마찬가지로 한개의 예제만 을 표기한다.<packagesappsGallerytestssrccomandroidcameragalleryImageListUberUnitTests.java>public class ImageListUberUnitTests extends AndroidTestCase { 13/19
  14. 14. 테크바일개발그룹 public void testTheOrderOfGetImageAt() {MockImageListlistA = new MockImageList();MockImageListlistB = new MockImageList();listA.addImage(new MockImage(2, 2));listA.addImage(new MockImage(0, 0));listB.addImage(new MockImage(1, 1));ImageListUberuber = new ImageListUber( new IImageList[] {listA, listB}, ImageManager.SORT_DESCENDING);assertEquals(2, getImageAt(uber, 0).fullSizeImageId());assertEquals(1, getImageAt(uber, 1).fullSizeImageId());assertEquals(0, getImageAt(uber, 2).fullSizeImageId());uber.close();uber = new ImageListUber( new IImageList[] {listA, listB}, ImageManager.SORT_DESCENDING);assertEquals(2, getImageAt(uber, 0).fullSizeImageId());assertEquals(1, getImageAt(uber, 1).fullSizeImageId());assertEquals(0, getImageAt(uber, 2).fullSizeImageId());uber.close(); }}이상에서 본 것처럼 각 어플은 각각의 방식으로 Unit Test를 구현하고 있는데, 어떤 방식으로 테스트를 구현할 것인지에 대한 검토가 필요하다.  기능 단위 검증: 기능이나 시나리오를 test case로 삼는 방식  API 단위 검증: class method에 대해 정상/비정상 parameter 경우들로 호출하여 그 결과를 확인하는 것을 test case로 삼는 방식여기에서 사용된 기능 단위 검증이나 API 단위 검증이라는 용어는 본 문서를 작성하는 과정에서 임의로 사용한 것으로 공식적인 것은 아니지만, 1차적으로 생각할 수 있는 unit test에 대한 구현을 위한 접근방법의 손쉬운 분류 방식이 될 수 있다. 결국 어떤 방식으로 unittest를 구현하더라도, 충분히 시험하고 있는지 어떤지에 대한 척도가 필요하다는 결론이 나오게 된다. 다음 장에서는 test coverage에 대해 다루기로 한다. 14/19
  15. 15. 테크바일개발그룹4. Test Coverage4.1. Test Coverage란?<http://en.wikipedia.org/wiki/Software_testing>Techniques used in white-box testing include:- API testing : testing of the application using public and private APIs- Code coverage : creating tests to satisfy some criteria of code coverage (e.g., the testdesigner can create tests to cause all statements in the program to be executed at least once)- Fault injection methods : intentionally introducing faults to gauge the efficacy of testingstrategies- Mutation testing methods- Static testing methodsCode coverage as a software metric can be reported as a percentage for:- Function coverage, which reports on functions executed- Statement coverage, which reports on the number of lines executed to complete the test100% statement coverage ensures that all code paths, or branches (in terms of control flow) areexecuted at least once. This is helpful in ensuring correct functionality, but not sufficient sincethe same code may process different inputs correctly or incorrectly.<http://www.udacity.com/wiki/CS258%20Unit%202>##5. Test coverage##Test coverage let’s us assign a score to a collection of test cases, and so lets be a little bitmore rigorous about it.So test coverage is really is a measure of the proportion of a program exercised during testing.So, for example, we’ve just talked about measuring a number of functions out of the totalnumber of functions or exercise by some test that we had. What’s good about test coverage is itgives us a score, gives us something objective that we can use to try figure out how well we’redoing. Additionally, when coverage is less than 100%, that is to say, as in our example, wherewe had failed to execute all of the functions in the software under test, we know what we needto do to get full coverage. We know what the functions are that we need to execute. Now, wesimply need to construct test cases and execute those functions.So, these are the good things about test coverage.On the other hand, there are also some disadvantages.First of all, test coverage, because it is a white box metric that is derived from the source code 15/19
  16. 16. 테크바일개발그룹for our system is not good at helping us find bugs of omission, that is to say bugs were simplyleft out of something that we should have implemented.4.2. ANT 설치하기<http://developer.android.com/tools/building/building-cmdline.html>If you dont have Ant, you can obtain it from the Apache Ant home page. Install it and make sureit is in your executable PATH. Before calling Ant, you need to declare the JAVA_HOMEenvironment variable to specify the path to where the JDK is installed.<http://ant.apache.org/faq.html>What is Apache Ant?Ant is a Java-based build tool. In theory, it is kind of like Make, without Makeswrinkles and with the full portability of pure Java code.Why do you call it Ant?According to Ants original author, James Duncan Davidson, the name is anacronym for "Another Neat Tool".  바이너리를 다운로드 하여 압축을 풀면 일단 설치가 거의 다 된 것이다.  환경변수는 PATH에 ANT의 bin 폴더를 추가하고, JAVA_HOME 을 설정한다. 16/19
  17. 17. 테크바일개발그룹4.3. ANT cmdline빌드를 위한 build.xml 만들기<http://blackriverweb.com/2012/02/android-continuous-integration-with-ant-and-jenkins-part-1/>Go to your project directory with console and run the following command:android update project -p . [-n _PROJECT_NAME_]Note that “.” (dot) after -p (path to project) flag, means “current folder”.It will update and rebuild your Android project files and create build.xml file, which will be usedby ANT to build your project.Then go to your test project folder with console and run update command for the test project:android update test-project -m _PATH_TO_ANDROID_PROJECT -p _TEST_PROJECT_PATH_At this point, we have two projects with prepared and build.xml files.E:AndroidEclipseWorkspaceSimpleGroupBell>android update project -p . -n SimpleGroupBellE:AndroidEclipseWorkspaceSimpleGroupBellTests>android update test-project -m..SimpleGroupBell -p .4.4. ANT를 사용하여 Code Coverage Enable로 cmdline빌드하기 17/19
  18. 18. 테크바일개발그룹ant all clean은 all에서 에러가 나서 all 삭제하고 실행함결과물 분석 필요!아래 두 url에서 coverage 결과물 경로 확인하자.<http://blackriverweb.com/2012/02/android-continuous-integration-with-ant-and-jenkins-part-1/>Go to your project folder and run:ant clean debugThis command should start compilation.Afterwards, cd to your test project folder, start Android emulator and run in console:ant clean emma debug install testThis command will build the test project, run code coverage report with EMMA tool, install APKinto emulator and run unit tests with JUnit on deviceYou’ll see the code coverage and unit tests results in your console window.http://codemuri.tistory.com/826 18/19
  19. 19. 테크바일개발그룹<http://developer.android.com/tools/building/building-cmdline.html>ant emma debug install testBuilds a test project and the tested project, installs both .apk files, and runs the tests with codecoverage enabled.<http://developer.android.com/reference/android/test/InstrumentationTestRunner.html>To generate EMMA code coverage: -e coverage true Note: this requires an emma instrumentedbuild. By default, the code coverage results file will be saved in a /data//coverage.ec file, unlessoverridden by coverageFile flag  추가적인 이론과 관련하여 udacity도 추천하자. 19/19

×