Activity的单元测试

Activity 的单元测试,每个Activity都是单独运行的,独立于系统环境。做单元测试的时候同个应用中的Activity互不相连,互相独立,每个Activity会单独启动,执行完测试用例后,Activity自动关闭。下面的图是android.test类图结构。 

 
Activity的单元测试
 

 

 InstrumentationTestCase类

继承自JUnit TestCase类,并可以使用Instrumentation框架,用于测试Activity。使用Instrumentation,Android可以向程序发送事件来自动进行UI测试,并可以精确控制Activity的启动,监测Activity生命周期的状态。

基类是InstrumentationTestCase。它的所有子类都能发送按键或触摸事件给UI。子类还可以注入一个模拟的Intent。

 

子类有:

n  ActivityTestCase——Activity测试类的基类。

n  SingleLaunchActivityTestCase——测试单个Activity的类。它能触发一次setup()和tearDown(),而不是每个方法调用时都触发。如果你的测试方法都是针对同一个Activity的话,那就使用它吧。

n  ActivityUnitTestCase——对单个Activity进行单一测试的类。使用它,你可以注入模拟的Context或Application,或者两者。它用于对Activity进行单元测试。不同于其它的Instrumentation类,这个测试类不能注入模拟的Intent。

n  ActivityInstrumentationTestCase2——在正常的系统环境中测试单个Activity的类。你不能注入一个模拟的Context,但你可以注入一个模拟的Intent。另外,你还可以在UI线程(应用程序的主线程)运行测试方法,并且可以给应用程序UI发送按键及触摸事件。

n  SyncBaseInstrumentation——测试Content Provider同步性的类。它使用Instrumentation在启动测试同步性之前取消已经存在的同步对象。

 

Avtivity单元测试简单举例如下:

被测类:

publicclass MainActivity extends ActionBarActivity {

   @Override

   protectedvoid onCreate(Bundle savedInstanceState) {

      super.onCreate(savedInstanceState);

      setContentView(R.layout.activity_main);

      View toLoginView = findViewById(R.id.to_login);

      mUsernameView = (EditText) //输入框

mMainActivity.findViewById(R.id.username); //提交按钮

   toLoginView.setOnClickListener(new View.OnClickListener(){

         publicvoid onClick(View view) {

            Intent intent = new Intent(getApplicationContext(),

                   LoginActivity.class);

            startActivity(intent);

         }

      });

   }

}

 

 

测试类:

publicclass MainActivityTests extends

      ActivityInstrumentationTestCase2<MainActivity> {

 

   private MainActivity mMainActivity;

   private Instrumentation mInstrumentation;

   private View mToLoginView;

   privatestaticinti = 0;

 

   // 此构造函数一定要提供

   public MainActivityTests() {

      super(MainActivity.class);

   }

 

   @Override

   protectedvoid setUp() throws Exception {

      super.setUp();

      // 如果要发送键盘事件一定要关闭触摸模式。不然键盘事件将被忽略。

      setActivityInitialTouchMode(false);

      // 可以发送键盘事件的对象

      mInstrumentation = getInstrumentation();

      // 启动avtivity,此函数每执行一次,activity就会启动一次。

      mMainActivity = getActivity();

      // 输入框

      mUsernameView = (EditText) mMainActivity.findViewById(R.id.username);

      // 提交按钮

      mToLoginView = mMainActivity.findViewById(R.id.to_login);

   }

 

   publicvoid testPreConditions() {

      assertTrue(mToLoginView != null);

   }

 

   publicvoid testToLogin() {

      //和UI相关的操作要放在UI线程中执行。

      /*

       * instrumentation.runOnMainSync();等同于一下两个函数

       * mActivity.runOnUiThread();//主线程中运行UI操作

       * mInstrument.waitForIdleSync();//等待UI同步

       */

      // mMainActivity.runOnUiThread(new Runnable() {

      // public void run() {

      // mUsernameView.requestFocus();

      // }

      // });

      // // 因为测试用例运行在单独的线程上,这里最好要

      // // 同步application,等待其执行完后再运行

      // mInstrumentation.waitForIdleSync();

 

      mInstrumentation.runOnMainSync(new Runnable() {

 

         @Override

         publicvoid run() {

            mUsernameView.requestFocus();//获得焦点

         }

      });

      sendKeys(KeyEvent.KEYCODE_Y, KeyEvent.KEYCODE_U, KeyEvent.KEYCODE_A, KeyEvent.KEYCODE_U);//输入字符

 

      mInstrumentation.runOnMainSync(new Runnable() {

         @Override

         publicvoid run() {

            mToLoginView.requestFocus();

            mToLoginView.performClick();//执行提交按钮的click事件

         }

      });

   }

 

}

相关推荐