文章转载于chinaunix的易水工作室

以前的博客中介绍过了如何用intrumentation进行android单元测试,其实还有一种方法同样可以,那就是利用AndroidTestCase来做单元测试,intrumentationTestCaseAndroidTestCase都是Junit.framwork.TestCase的子类,二者代表不用的方向。

如果想通过AndroidTestCase,大致可以通过以下几个步骤实现:

  1. 添加自己的test case code,让他们继承自AndroidTestCase

  2. 定义自己的testSuite类,用来管理test cases.

  3. 定义自己的testRunner,用来执行测试

下面首先来看一下这种方法所涉及到的android的类以及接口。

AndroidTestCase

Android test cases classes需要从这个类派生出来,而不再是从junit.framework.TestCase.二者之间的最主要区别就是Android test cases提供了一个方法getContext()来获取当前的上下文变量,这在android测试中很重要的,因为很多的android api都需要context

AndroidTestCase主要成员:

setUp()//Setsupthefixture,forexample,openanetworkconnection.tearDown()//Tearsdownthefixture,forexample,closeanetworkconnection.testAndroidTestCaseSetupProperly()


TestSuite(in package junit.package)

一个TestSuite就是一系列test case的集合。通过testsuite可以更好的来管理test case

TestSuite主要成员:

VoidaddTest (Test test) //Adds a test to the suite.

voidaddTestSuite(Class testClass)//Adds the tests from the given class to the suite

下面是一小段往test suite中添加test case的示例:

TestSuitesuite=newTestSuite();suite.addTest(newMathTest("testAdd"));//Addsatesttothesuite.suite.addTest(newMathTest("testDivideByZero"));//或者可以通过addTestSuite()来添加suite.addTestSuite(MathTest.class);

TestListener(in package junit.framework)

这是一个interface,用来监听测试进程

有以下4Public Methods:

abstractvoidaddError(Testtest,Throwablet)//Anerroroccurred.abstractvoidaddFailure(Testtest,AssertionFailedErrort)//Afailureoccurred.abstractvoidendTest(Testtest)//Atestended.abstractvoidstartTest(Testtest)//Ateststarted.


AndroidTestRunner

继承自class junit.runner.BaseTestRunner,但是它没有提供ui,甚至来一个基于consoleUI都没有,所以,如果想要很好的查看测试结果的话,你需要自己来处理来自于test runnercallback函数。一会可以通过例子演示一下

AndroidTestRunner主要方法:

SetTest();runTest()addTestListener()setContext()


如果要使用AndroidTestRunner,需要在permission in manifest.xml中添加权限:

<uses-libraryandroid:name="android.test.runner"/>


最后,通过一个实例来演示一下:

1. 写一个test case:

MathTest.java

packagecom.ut.prac;importandroid.test.AndroidTestCase;importandroid.util.Log;publicclassMathTestextendsAndroidTestCase{protectedinti1;protectedinti2;staticfinalStringLOG_TAG="MathTest";publicvoidsetUp(){i1=2;i2=3;}publicvoidtestAdd(){Log.d(LOG_TAG,"testAdd");assertTrue(LOG_TAG+"1",((i1+i2)==5));}publicvoidtestAndroidTestCaseSetupProperly(){super.testAndroidTestCaseSetupProperly();Log.d(LOG_TAG,"testAndroidTestCaseSetupProperly");}}

2. 定义一个test suite类。

ExampleSuite.java

packagecom.ut.prac;importjunit.framework.TestSuite;publicclassExampleSuiteextendsTestSuite{publicExampleSuite(){addTestSuite(MathTest.class);}}

3.定义test runner,以及构建UI来处理测试流程,查看测试结果等。

MyJUnitExample.java

packagecom.ut.prac;importjunit.framework.Test;importjunit.framework.TestListener;importandroid.app.Activity;importandroid.os.Bundle;importandroid.test.AndroidTestRunner;importandroid.util.Log;importandroid.view.View;importandroid.widget.Button;importandroid.widget.TextView;importandroid.widget.Toast;publicclassMyJUnitExampleextendsActivity{staticfinalStringLOG_TAG="junit";ThreadtestRunnerThread=null;/**Calledwhentheactivityisfirstcreated.*/@OverridepublicvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);ButtonlauncherButton=(Button)findViewById(R.id.launch_button);launcherButton.setOnClickListener(newView.OnClickListener(){publicvoidonClick(Viewview){startTest();}});}privatesynchronizedvoidstartTest(){if((testRunnerThread!=null)&&!testRunnerThread.isAlive())testRunnerThread=null;if(testRunnerThread==null){testRunnerThread=newThread(newTestRunner(this));testRunnerThread.start();}elseToast.makeText(this,"Testisstillrunning",Toast.LENGTH_SHORT).show();}}classTestDisplayimplementsRunnable{publicenumdisplayEvent{START_TEST,END_TEST,ERROR,FAILURE,}displayEventev;StringtestName;inttestCounter;interrorCounter;intfailureCounter;TextViewstatusText;TextViewtestCounterText;TextViewerrorCounterText;TextViewfailureCounterText;publicTestDisplay(displayEventev,StringtestName,inttestCounter,interrorCounter,intfailureCounter,TextViewstatusText,TextViewtestCounterText,TextViewerrorCounterText,TextViewfailureCounterText){this.ev=ev;this.testName=testName;this.testCounter=testCounter;this.errorCounter=errorCounter;this.failureCounter=failureCounter;this.statusText=statusText;this.testCounterText=testCounterText;this.errorCounterText=errorCounterText;this.failureCounterText=failureCounterText;}publicvoidrun(){StringBufferstatus=newStringBuffer();switch(ev){caseSTART_TEST:status.append("Starting");break;caseEND_TEST:status.append("Ending");break;caseERROR:status.append("Error:");break;caseFAILURE:status.append("Failure:");break;}status.append(":");status.append(testName);statusText.setText(newString(status));testCounterText.setText("Tests:"+testCounter);errorCounterText.setText("Errors:"+errorCounter);failureCounterText.setText("Failure:"+failureCounter);}}classTestRunnerimplementsRunnable,TestListener{staticfinalStringLOG_TAG="TestRunner";inttestCounter;interrorCounter;intfailureCounter;TextViewstatusText;TextViewtestCounterText;TextViewerrorCounterText;TextViewfailureCounterText;ActivityparentActivity;publicTestRunner(ActivityparentActivity){this.parentActivity=parentActivity;}publicvoidrun(){testCounter=0;errorCounter=0;failureCounter=0;statusText=(TextView)parentActivity.findViewById(R.id.status);testCounterText=(TextView)parentActivity.findViewById(R.id.testCounter);errorCounterText=(TextView)parentActivity.findViewById(R.id.errorCounter);failureCounterText=(TextView)parentActivity.findViewById(R.id.failureCounter);Log.d(LOG_TAG,"Teststarted");AndroidTestRunnertestRunner=newAndroidTestRunner();testRunner.setTest(newExampleSuite());testRunner.addTestListener(this);testRunner.setContext(parentActivity);testRunner.runTest();Log.d(LOG_TAG,"Testended");}//TestListenerpublicvoidaddError(Testtest,Throwablet){Log.d(LOG_TAG,"addError:"+test.getClass().getName());Log.d(LOG_TAG,t.getMessage(),t);++errorCounter;TestDisplaytd=newTestDisplay(TestDisplay.displayEvent.ERROR,test.getClass().getName(),testCounter,errorCounter,failureCounter,statusText,testCounterText,errorCounterText,failureCounterText);parentActivity.runOnUiThread(td);}publicvoidendTest(Testtest){Log.d(LOG_TAG,"endTest:"+test.getClass().getName());TestDisplaytd=newTestDisplay(TestDisplay.displayEvent.END_TEST,test.getClass().getName(),testCounter,errorCounter,failureCounter,statusText,testCounterText,errorCounterText,failureCounterText);parentActivity.runOnUiThread(td);}publicvoidstartTest(Testtest){Log.d(LOG_TAG,"startTest:"+test.getClass().getName());++testCounter;TestDisplaytd=newTestDisplay(TestDisplay.displayEvent.START_TEST,test.getClass().getName(),testCounter,errorCounter,failureCounter,statusText,testCounterText,errorCounterText,failureCounterText);parentActivity.runOnUiThread(td);}@OverridepublicvoidaddFailure(Testtest,junit.framework.AssertionFailedErrort){//TODOAuto-generatedmethodstubLog.d(LOG_TAG,"addFailure:"+test.getClass().getName());Log.d(LOG_TAG,t.getMessage(),t);++failureCounter;TestDisplaytd=newTestDisplay(TestDisplay.displayEvent.FAILURE,test.getClass().getName(),testCounter,errorCounter,failureCounter,statusText,testCounterText,errorCounterText,failureCounterText);parentActivity.runOnUiThread(td);}}

4. 最后是xml文件

Manifest.xml

<?xmlversion="1.0"encoding="utf-8"?><manifestxmlns:android="http://schemas.android.com/apk/res/android"package="com.ut.prac"android:versionCode="1"android:versionName="1.0"><uses-permissionandroid:name="android.permission.WRITE_CONTACTS"/><uses-permissionandroid:name="android.permission.READ_CONTACTS"/><applicationandroid:icon="@drawable/icon"android:label="@string/app_name"><uses-libraryandroid:name="android.test.runner"/><activityandroid:name=".MyJUnitExample"android:label="@string/app_name"><intent-filter><actionandroid:name="android.intent.action.MAIN"/><categoryandroid:name="android.intent.category.LAUNCHER"/></intent-filter></activity></application><uses-sdkandroid:minSdkVersion="3"/></manifest>

Mail.xml

<?xmlversion="1.0"encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="fill_parent"android:layout_height="fill_parent"><Buttonandroid:id="@+id/launch_button"android:text="@string/launch_test"android:layout_width="wrap_content"android:layout_height="wrap_content"/><TextViewandroid:id="@+id/status"android:layout_width="fill_parent"android:layout_height="wrap_content"android:text=""/><TextViewandroid:id="@+id/testCounter"android:layout_width="fill_parent"android:layout_height="wrap_content"android:text=""/><TextViewandroid:id="@+id/errorCounter"android:layout_width="fill_parent"android:layout_height="wrap_content"android:text=""/><TextViewandroid:id="@+id/failureCounter"android:layout_width="fill_parent"android:layout_height="wrap_content"android:text=""/></LinearLayout>


更多相关文章

  1. 如何添加Android返回键的退出功能
  2. Android(安卓)init.rc BOOTCLASSPATH
  3. 2011.09.13(3)——— android 添加快捷方式并且图标上添加数字
  4. android自定义属性之format介绍
  5. 去掉所有Activity界面标题栏、强制横屏竖屏
  6. Android(安卓)Makefile中是 如何识别 TARGET_PRODUCT 的
  7. android 完美退出所有Activity的demo
  8. Android(安卓)自定义带圆角的dialog
  9. Android之自定义ContentProvider详解

随机推荐

  1. Android(安卓)自定义 View 实例 随手拖动
  2. 图库选择
  3. Android(安卓)查看大图(直接复制可以用)
  4. Android(安卓)Studio音乐播放器and视频播
  5. android 下拉刷新控件
  6. ViewPager初步用法(二)
  7. ListActivity show List
  8. SurfaceView基本使用
  9. notification android原生消息通知代码详
  10. android路径获取