Android单元测试之JUnit

2024-06-16 10:08
文章标签 android junit 单元测试

本文主要是介绍Android单元测试之JUnit,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

       随着最近几年测试方面的工作慢慢火热起来,经常看见有招聘测试工程师的招聘信息。在Java中有单元测试这么一个JUnit

方式,Android目前主要编写的语言是Java,所以在Android开发中也会有那么一个单元测试---JUnit。从Android的开发环境搭建可

以看出来,Android先要在JDK的基础上,然后导入Android自己的SDK开发环境,当然Android的单元测试JUnit是专门测试Android

 APP里面的方法性能等。Android最常见的测试----JUnit。Android提供了一系列强大的测试工具,它针对Android的环境,扩展了

业内标准的JUnit测试框架。尽管你可以使用JUnit测试Android工程,但Android工具允许你为应用程序的各个方面进行更为复杂的

测试,包括单元层面及框架层面。


一、Android测试环境的主要特征有:
 1、可以访问Android系统对象。
 2、Instrumentation框架可以控制和测试应用程序。
 3、Android系统常用对象的模拟版本。
 4、运行单个test或test suite的工具,带或不带Instrumentation。
 5、支持以Eclipse的ADT插件和命令行方式管理Test和Test工程。


二、JUnit核心框架-----Instrumentation框架:

     Android测试环境的核心是一个Instrumentation框架,在这个框架下,你的测试应用程序可以精确控制应用程序。使用Instrumentation,你可以在主程序启动之前,创建模拟的系统对象,如Context;控制应用程序的多个生命周期;发送UI事件给应用程序;在执行期间检查程序状态。Instrumentation框架通过将主程序和测试程序运行在同一个进程来实现这些功能。
    通过在测试工程的manifest文件中添加<instrumentation>元素来指定要测试的应用程序。这个元素的特性指明了要测试的应用程序包名,以及告诉Android如何运行测试程序。
 在Android中,测试程序也是Android程序,因此,它和被测试程序的书写方式有很多相同的地方。SDK工具能帮助你同时创建主程序工程及它的测试工程。你可以通过Eclipse的ADT插件或者命令行来运行Android测试。Eclipse的ADT提供了大量的工具来创建测试用例,运行以及查看结果。

       首先,我们来了解一下android的测试类的层次结构:

         

     Testing API
          Android提供了基于JUnit测试框架的测试API来书写测试用例和测试程序。另外,Android还提供了强大的Instrumentation框架,允许测试用例访问程序的状态及运行时对象。

    JUnit TestCase类
          继承自JUnit的TestCase,不能使用Instrumentation框架。但这些类包含访问系统对象(如Context)的方法。使用Context,你可以浏览资源,文件,数据库等等。基类是AndroidTestCase,一般常见的是它的子类,和特定组件关联。

      子类有:

        1、ApplicationTestCase——测试整个应用程序的类。它允许你注入一个模拟的Context到应用程序中,在应用程序启动之前初始化测试参数,并在应用程序结束之后销毁之前检查应用程序。
        2、ProviderTestCase2——测试单个ContentProvider的类。因为它要求使用MockContentResolver,并注入一个IsolatedContext,因此Provider的测试是与OS孤立的。
        3、ServiceTestCase——测试单个Service的类。你可以注入一个模拟的Context或模拟的Application(或者两者),或者让Android为你提供Context和MockApplication。

    Instrumentation TestCase类
         继承自JUnit TestCase类,并可以使用Instrumentation框架,用于测试Activity。使用Instrumentation,Android可以向程序发送事件来自动进行UI测试,并可以精确控制Activity的启动,监测Activity生命周期的状态。基类是InstrumentationTestCase。它的所有子类都能发送按键或触摸事件给UI。子类还可以注入一个模拟的Intent。

   子类有:
1、 ActivityTestCase——Activity测试类的基类。
2、 SingleLaunchActivityTestCase——测试单个Activity的类。它能触发一次setup()和tearDown(),而不是每个方法调用时都触发。如果你的测试方法都是针对同一个Activity的话,那就使用它吧。
3、 SyncBaseInstrumentation——测试Content Provider同步性的类。它使用Instrumentation在启动测试同步性之前取消已经存在的同步对象。
4、ActivityUnitTestCase——对单个Activity进行单一测试的类。使用它,你可以注入模拟的Context或Application,或者两者。它用于对Activity进行单元测试。
不同于其它的Instrumentation类,这个测试类不能注入模拟的Intent。
5、 ActivityInstrumentationTestCase2——在正常的系统环境中测试单个Activity的类。你不能注入一个模拟的Context,但你可以注入一个模拟的Intent。另外,你还可以在UI线程(应用程序的主线程)运行测试方法,并且可以给应用程序UI发送按键及触摸事件。


三、Instrumentation框架的测试用法

       Instrumentation和Activity有点类似,只不过Activity是需要一个界面的,而Instrumentation并不是这样的,我们可以将它理解为一种没有图形界面的,具有启动能力的,用于监控其他类(用Target Package声明)的工具类。

       下面通过一个简单的例子来讲解Instrumentation的基本测试方法。

          1.首先建立一个Android project,类名为Sample,代码如下:
public class Sample extends Activity {
   private TextView myText = null;
   private Button button = null;
 
   @Override
   public void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.main);
       myText = (TextView) findViewById(R.id.text1);
       button = (Button) findViewById(R.id.button1);
       button.setOnClickListener(new OnClickListener() {
           @Override
           public void onClick(View arg0) {
               myText.setText("Hello Android");
           }
       });
   }
 
   public int add(int i, int j) {
       return (i + j);
   }
}
这个程序的功能比较简单,点击按钮之后,TextView的内容由Hello变为Hello Android.同时,在这个类中,我还写了一个简单的add方法,没有被调用,仅供测试而已。

      2. 在src文件夹中添加一个测试包,在测试包中添加一个测试类SampleTest
测试类的代码如下:
public class SampleTest extends InstrumentationTestCase {
   private Sample sample = null;
   private Button button = null;
   private TextView text = null;
 
   /*
    * 初始设置
    * @see junit.framework.TestCase#setUp()
    */
   @Override
   protected void setUp()  {
       try {
           super.setUp();
       } catch (Exception e) {
           e.printStackTrace();
       }
       Intent intent = new Intent();
       intent.setClassName("com.hustophone.sample", Sample.class.getName());
       intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
       sample = (Sample) getInstrumentation().startActivitySync(intent);
       text = (TextView) sample.findViewById(R.id.text1);
       button = (Button) sample.findViewById(R.id.button1);
   }
 
   /*
    * 垃圾清理与资源回收
    * @see android.test.InstrumentationTestCase#tearDown()
    */
   @Override
   protected void tearDown()  {
       sample.finish();
       try {
           super.tearDown();
       } catch (Exception e) {
           e.printStackTrace();
       }
   }
 
   /*
    * 活动功能测试
    */
   public void testActivity() throws Exception {
       Log.v("testActivity", "test the Activity");
       SystemClock.sleep(1500);
       getInstrumentation().runOnMainSync(new PerformClick(button));
       SystemClock.sleep(3000);
       assertEquals("Hello Android", text.getText().toString());
   }
 
   /*
    * 模拟按钮点击的接口
    */
   private class PerformClick implements Runnable {
       Button btn;
       public PerformClick(Button button) {
           btn = button;
       }
 
       public void run() {
           btn.performClick();
       }
   }
   /*
    * 测试类中的方法
    */
   public void testAdd() throws Exception{
       String tag = "testAdd";
       Log.v(tag, "test the method");
       int test = sample.add(1, 1);
       assertEquals(2, test);
   }
}

       下面来简单讲解一下代码:
setUp()和tearDown()都是受保护的方法,通过继承可以覆写这些方法。
          在android Developer中有如下的解释
       protected void setUp ()
Since: API Level 3
Sets up the fixture, for example, open a network connection. This method is called before a test is executed.
                protected void tearDown ()
Since: API Level 3
Make sure all resources are cleaned up and garbage collected before moving on to the next test. Subclasses that override this method should make sure they call super.tearDown() at the end of the overriding method.

setUp ()用来初始设置,如启动一个Activity,初始化资源等。
tearDown ()则用来垃圾清理与资源回收

在testActivity()这个测试方法中,我模拟了一个按钮点击事件,然后来判断程序是否按照预期的执行。在这里PerformClick这个方法继承了Runnable接口,通过新的线程来执行模拟事件,之所以这么做,是因为如果直接在UI线程中运行可能会阻滞UI线程。

       2.要想正确地执行测试,还需要修改AndroidManifest.xml这个文件.
          <!--用于引入测试库-->
                <uses-library android:name="android.test.runner" />
                <activity android:name=".Sample" android:label="@string/app_name">
                       <intent-filter>
                                <action android:name="android.intent.action.MAIN" />
                                 <category android:name="android.intent.category.LAUNCHER" />
                      </intent-filter>
               </activity>
          
        <uses-sdk android:minSdkVersion="3" />
        <!--表示被测试的目标包与instrumentation的名称。-->
         <instrumentation android:targetPackage="com.hustophone.sample"                                                                   android:name="android.test.InstrumentationTestRunner" />

        经过以上步骤,下面可以开始测试了。测试方法也有以下几种,下面介绍两个常用的方法:

       (1) 用Eclipse集成的JUnit工具
               在Eclipse中选择工程Sample,单击右键,在Run as子菜单选项中选择Android JUnit Test
    


同时可以通过LogCat工具查看信息


 

        (2) 通过模拟器运行单元测试

            点击模拟器界面的Dev Tools菜单

           再点击Instrumentation选项,进入Instrumentation菜单


                  


          这里有一个InstrumentationTestRunner,它是测试的入口,点击这个选项,就可以自动运行我们的测试代码。以下为运行结果:

       按钮点击前

       按钮点击后
  

至此,一个简单的测试过程结束了。当然,android的测试内容还有很多,也有比较复杂的,我会在以后的学习过程中继续分享我的体会。好了,今天就到这里吧!


这篇关于Android单元测试之JUnit的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/1066167

相关文章

Android学习总结之Java和kotlin区别超详细分析

《Android学习总结之Java和kotlin区别超详细分析》Java和Kotlin都是用于Android开发的编程语言,它们各自具有独特的特点和优势,:本文主要介绍Android学习总结之Ja... 目录一、空安全机制真题 1:Kotlin 如何解决 Java 的 NullPointerExceptio

Android NDK版本迭代与FFmpeg交叉编译完全指南

《AndroidNDK版本迭代与FFmpeg交叉编译完全指南》在Android开发中,使用NDK进行原生代码开发是一项常见需求,特别是当我们需要集成FFmpeg这样的多媒体处理库时,本文将深入分析A... 目录一、android NDK版本迭代分界线二、FFmpeg交叉编译关键注意事项三、完整编译脚本示例四

Android与iOS设备MAC地址生成原理及Java实现详解

《Android与iOS设备MAC地址生成原理及Java实现详解》在无线网络通信中,MAC(MediaAccessControl)地址是设备的唯一网络标识符,本文主要介绍了Android与iOS设备M... 目录引言1. MAC地址基础1.1 MAC地址的组成1.2 MAC地址的分类2. android与I

Android 实现一个隐私弹窗功能

《Android实现一个隐私弹窗功能》:本文主要介绍Android实现一个隐私弹窗功能,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧... 效果图如下:1. 设置同意、退出、点击用户协议、点击隐私协议的函数参数2. 《用户协议》、《隐私政策》设置成可点击的,且颜色要区分出来res/l

解决tomcat启动时报Junit相关错误java.lang.ClassNotFoundException: org.junit.Test问题

《解决tomcat启动时报Junit相关错误java.lang.ClassNotFoundException:org.junit.Test问题》:本文主要介绍解决tomcat启动时报Junit相... 目录tomcat启动时报Junit相关错误Java.lang.ClassNotFoundException

Android实现一键录屏功能(附源码)

《Android实现一键录屏功能(附源码)》在Android5.0及以上版本,系统提供了MediaProjectionAPI,允许应用在用户授权下录制屏幕内容并输出到视频文件,所以本文将基于此实现一个... 目录一、项目介绍二、相关技术与原理三、系统权限与用户授权四、项目架构与流程五、环境配置与依赖六、完整

Android 12解决push framework.jar无法开机的方法小结

《Android12解决pushframework.jar无法开机的方法小结》:本文主要介绍在Android12中解决pushframework.jar无法开机的方法,包括编译指令、框架层和s... 目录1. android 编译指令1.1 framework层的编译指令1.2 替换framework.ja

Android开发环境配置避坑指南

《Android开发环境配置避坑指南》本文主要介绍了Android开发环境配置过程中遇到的问题及解决方案,包括VPN注意事项、工具版本统一、Gerrit邮箱配置、Git拉取和提交代码、MergevsR... 目录网络环境:VPN 注意事项工具版本统一:android Studio & JDKGerrit的邮

Android实现定时任务的几种方式汇总(附源码)

《Android实现定时任务的几种方式汇总(附源码)》在Android应用中,定时任务(ScheduledTask)的需求几乎无处不在:从定时刷新数据、定时备份、定时推送通知,到夜间静默下载、循环执行... 目录一、项目介绍1. 背景与意义二、相关基础知识与系统约束三、方案一:Handler.postDel

Android使用ImageView.ScaleType实现图片的缩放与裁剪功能

《Android使用ImageView.ScaleType实现图片的缩放与裁剪功能》ImageView是最常用的控件之一,它用于展示各种类型的图片,为了能够根据需求调整图片的显示效果,Android提... 目录什么是 ImageView.ScaleType?FIT_XYFIT_STARTFIT_CENTE