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数据库Room的实际使用过程总结

《Android数据库Room的实际使用过程总结》这篇文章主要给大家介绍了关于Android数据库Room的实际使用过程,详细介绍了如何创建实体类、数据访问对象(DAO)和数据库抽象类,需要的朋友可以... 目录前言一、Room的基本使用1.项目配置2.创建实体类(Entity)3.创建数据访问对象(DAO

Android WebView的加载超时处理方案

《AndroidWebView的加载超时处理方案》在Android开发中,WebView是一个常用的组件,用于在应用中嵌入网页,然而,当网络状况不佳或页面加载过慢时,用户可能会遇到加载超时的问题,本... 目录引言一、WebView加载超时的原因二、加载超时处理方案1. 使用Handler和Timer进行超

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影

android-opencv-jni

//------------------start opencv--------------------@Override public void onResume(){ super.onResume(); //通过OpenCV引擎服务加载并初始化OpenCV类库,所谓OpenCV引擎服务即是 //OpenCV_2.4.3.2_Manager_2.4_*.apk程序包,存

从状态管理到性能优化:全面解析 Android Compose

文章目录 引言一、Android Compose基本概念1.1 什么是Android Compose?1.2 Compose的优势1.3 如何在项目中使用Compose 二、Compose中的状态管理2.1 状态管理的重要性2.2 Compose中的状态和数据流2.3 使用State和MutableState处理状态2.4 通过ViewModel进行状态管理 三、Compose中的列表和滚动

Android 10.0 mtk平板camera2横屏预览旋转90度横屏拍照图片旋转90度功能实现

1.前言 在10.0的系统rom定制化开发中,在进行一些平板等默认横屏的设备开发的过程中,需要在进入camera2的 时候,默认预览图像也是需要横屏显示的,在上一篇已经实现了横屏预览功能,然后发现横屏预览后,拍照保存的图片 依然是竖屏的,所以说同样需要将图片也保存为横屏图标了,所以就需要看下mtk的camera2的相关横屏保存图片功能, 如何实现实现横屏保存图片功能 如图所示: 2.mtk

android应用中res目录说明

Android应用的res目录是一个特殊的项目,该项目里存放了Android应用所用的全部资源,包括图片、字符串、颜色、尺寸、样式等,类似于web开发中的public目录,js、css、image、style。。。。 Android按照约定,将不同的资源放在不同的文件夹中,这样可以方便的让AAPT(即Android Asset Packaging Tool , 在SDK的build-tools目

Android fill_parent、match_parent、wrap_content三者的作用及区别

这三个属性都是用来适应视图的水平或者垂直大小,以视图的内容或尺寸为基础的布局,比精确的指定视图的范围更加方便。 1、fill_parent 设置一个视图的布局为fill_parent将强制性的使视图扩展至它父元素的大小 2、match_parent 和fill_parent一样,从字面上的意思match_parent更贴切一些,于是从2.2开始,两个属性都可以使用,但2.3版本以后的建议使

Android Environment 获取的路径问题

1. 以获取 /System 路径为例 /*** Return root of the "system" partition holding the core Android OS.* Always present and mounted read-only.*/public static @NonNull File getRootDirectory() {return DIR_ANDR