Android 单元测试过程详解

无鸯 发布于 2011/09/05 16:31
阅读 11K+
收藏 11

android源代码中每个app下中都自带了一个test用例,下面主要介绍下camra单元测试用例 在AndroidManifest.xml中标明了测试用例instrumentation函数入口

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2008 The Android Open Source Project

     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
     You may obtain a copy of the License at
  
          http://www.apache.org/licenses/LICENSE-2.0
  
     Unless required by applicable law or agreed to in writing, software
     distributed under the License is distributed on an "AS IS" BASIS,
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     See the License for the specific language governing permissions and
     limitations under the License.
-->

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.android.camera.tests">

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

    <instrumentation android:name="CameraLaunchPerformance"
            android:targetPackage="com.android.camera"
            android:label="Camera Launch Performance">
    </instrumentation>
    
    <instrumentation android:name="com.android.camera.CameraStressTestRunner"
             android:targetPackage="com.android.camera"
             android:label="Camera Stress Test InstrumentationRunner">
    </instrumentation>

    <instrumentation android:name="android.test.InstrumentationTestRunner"
             android:targetPackage="com.android.camera"
             android:label="Tests for Camera application."/>
</manifest>  

camera启动性能测试 

package com.android.camera;

import android.app.Activity;
import android.os.Bundle;
import android.test.LaunchPerformanceBase;

/**
 * Instrumentation class for Camera launch performance testing.
 */
public class CameraLaunchPerformance extends LaunchPerformanceBase {

    public static final String LOG_TAG = "CameraLaunchPerformance";

    public CameraLaunchPerformance() {
        super();
    }

    @Override
    public void onCreate(Bundle arguments) {
        super.onCreate(arguments);

        mIntent.setClassName(getTargetContext(), "com.android.camera.Camera");
        start();
    }

    /**
     * Calls LaunchApp and finish.
     */
    @Override
    public void onStart() {
        super.onStart();
        LaunchApp();
        finish(Activity.RESULT_OK, mResults);
    }
}

camera拍照压力测试,参数设定为反复拍照100次 

package com.android.camera.stress;

import com.android.camera.Camera;

import android.app.Instrumentation;
import android.test.ActivityInstrumentationTestCase2;
import android.test.suitebuilder.annotation.LargeTest;
import android.util.Log;
import android.view.KeyEvent;

/**
 * Junit / Instrumentation test case for camera test
 *
 * Running the test suite:
 *
 * adb shell am instrument \
 *    -e class com.android.camera.stress.ImageCapture \
 *    -w com.android.camera.tests/com.android.camera.CameraStressTestRunner
 *
 */

public class ImageCapture extends ActivityInstrumentationTestCase2 <Camera> {
    private String TAG = "ImageCapture";
    private static final int TOTAL_NUMBER_OF_IMAGECAPTURE = 100;
    private static final int TOTAL_NUMBER_OF_VIDEOCAPTURE = 100;
    private static final long WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN = 1000;
    private static final long WAIT_FOR_VIDEO_CAPTURE_TO_BE_TAKEN = 50000; //50seconds
    private static final long WAIT_FOR_PREVIEW = 1000; //1 seconds

    public ImageCapture() {
        super("com.android.camera", Camera.class);
    }

    @Override
    protected void setUp() throws Exception {
        getActivity();
        super.setUp();
    }

    @Override
    protected void tearDown() throws Exception {
        super.tearDown();
    }

    @LargeTest
    public void testImageCapture() {
        Instrumentation inst = getInstrumentation();
        try {
            for (int i = 0; i < TOTAL_NUMBER_OF_IMAGECAPTURE; i++) {
                Thread.sleep(WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN);
                inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_UP);
                inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER);
                Thread.sleep(WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN);
            }
        } catch (Exception e) {
            Log.v(TAG, e.toString());
        }
            assertTrue("testImageCapture", true);
    }

    @LargeTest
    public void testVideoCapture() {
        Instrumentation inst = getInstrumentation();
        //Switch to the video mode
        inst.sendKeyDownUpSync(KeyEvent.KEYCODE_MENU);
        inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER);
        try {
            for (int i = 0; i < TOTAL_NUMBER_OF_VIDEOCAPTURE; i++) {
                Thread.sleep(WAIT_FOR_PREVIEW);
                inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_UP);
                //record an video
                inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER);
                Thread.sleep(WAIT_FOR_VIDEO_CAPTURE_TO_BE_TAKEN);
                inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER);
                Thread.sleep(WAIT_FOR_PREVIEW);
                inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER);
            }
        } catch (Exception e) {
            Log.v(TAG, e.toString());
        }
            assertTrue("testVideoCapture", true);
    }

} 

如果想在android里面做单元测试,有两条基本的路子可行。 

第一, 就是java程序员最为熟悉和常用的JUnit, 但是由于目前android sdk (version 1.1)中只是提供了stubbed methods/classes,没有具体的实现代码,所以如果用JUnit的话,我们需要在运行单元测试时,一定要用JDK来运行,利用java命令来启动JUnit的某个Runner。如果是用Eclipse的话,可以在Run Configuration里新建一个JUnit。但是一定要记得在Classpath选项卡里将Bootstrap Entries中的Android Library改成JRE,并且添加junit.jar。具体的设置可以参考:http://developer.android.com/guide /appendix/faq/troubleshooting.html#addjunit。而且,更为遗憾的是,这种方法运行的JUnit运行在JDK之上的,而不是android,所以,只能测试一些和android无关的东西,比如业务逻辑,数据封装,数值计算等等。并不能测试android api。 

第二, 采用Instrumentation. Android单元测试的主入口是InstrumentationTestRunner。它相当于JUnit当中TestRunner的作用。你可以将 Instrumentation理解为一种没有图形界面的,具有启动能力的,用于监控其他类(用Target Package声明)的工具类。任何想成为Instrumentation的类必须继承android.app.Instrumentation。 

下面通过一个实例来看一下如何通过Instrumentation来做单元测试。 

Step 1.首先编写需要测试的activity: 

import android.app.Activity;
import android.os.Bundle;

public class AndroidUT extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
   
    public int add(int a, int b)
    {
        return a + b;
    }
}

Step 2. 

接下来编写测试类,其中主要来测试add()方法。我们在当前代码目录下,在新建一个文件夹,命名为test,并在里面新建了包com.android.ut.test。然后往里面新增加一个class.具体如下: 

import com.android.ut.AndroidUT;

import android.test.ActivityInstrumentationTestCase;

public class TestApp extends ActivityInstrumentationTestCase<AndroidUT> {
   
    public TestApp()
    {
        super("com.android.ut", AndroidUT.class);
    }
   
    public void testSum()
    {
        assertEquals(5, getActivity().add(2, 3));
    }   
} 

Step 3.最后一步就是要改一下Manifest文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.android.ut"
      android:versionCode="1"
      android:versionName="1.0.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".AndroidUT"
                  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-library android:name="android.test.runner" />
    </application>
    <instrumentation android:targetPackage="com.android.ut" android:name="android.test.InstrumentationTestRunner" android:label="Test Unit Tests"></instrumentation>
</manifest> 

需要注意的是,在这里面我加上了: 

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

以及: 

<instrumentation android:targetPackage="com.android.ut" 
		 android:name="android.test.InstrumentationTestRunner" 
		 android:label="Test Unit Tests">
</instrumentation>  

Step 4.运行 

首先通过模拟器运行一下AndroidUT,然后在命令行终端中运行 

adb shell am instrument -e class com.android.ut.test.TestApp -wcom.android.ut/android.test.InstrumentationTestRunner  

这样你就可以看到测试结果了

# am instrument -e class com.cn.test.TestApp -w com.cn/android.test.InstrumentationTestRunner

com.cn.test.TestApp:..
Test results for InstrumentationTestRunner=..
Time: 2.866

OK (2 tests) 

后台测试log日志信息 
D/AndroidRuntime(  941): >>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<<
D/AndroidRuntime(  941): CheckJNI is ON
D/AndroidRuntime(  941): --- registering native functions ---
D/FileBackupHelper_native(  941): register_android_backup_FileBackupHelper
D/ActivityManager(  581): Uninstalling process com.cn
I/ActivityManager(  581): Start proc com.cn for added application com.cn: pid=948 uid=10013 gids={}
I/TestRunner(  948): started: testSum(com.cn.test.TestApp)      //启动add()测试方法
I/ActivityManager(  581): Starting activity: Intent { act=android.intent.action.MAIN flg=0x10000000 cmp=com.cn/.AndroidUT }
I/ActivityManager(  581): Displayed activity com.cn/.AndroidUT: 645 ms (total 645 ms)
I/TestRunner(  948): finished: testSum(com.cn.test.TestApp)
I/TestRunner(  948): passed: testSum(com.cn.test.TestApp)
I/TestRunner(  948): started: testActivityTestCaseSetUpProperly(com.cn.test.TestApp)
I/ActivityManager(  581): Starting activity: Intent { act=android.intent.action.MAIN flg=0x10000000 cmp=com.cn/.AndroidUT }
I/ActivityManager(  581): Displayed activity com.cn/.AndroidUT: 412 ms (total 412 ms)
I/TestRunner(  948): finished: testActivityTestCaseSetUpProperly(com.cn.test.TestApp)
I/TestRunner(  948): passed: testActivityTestCaseSetUpProperly(com.cn.test.TestApp)
D/ActivityManager(  581): Uninstalling process com.cn
D/ActivityManager(  581): Force removing process ProcessRecord{43851fa0 948:com.cn/10013} (com.cn/10013)
D/AndroidRuntime(  941): Shutting down VM

加载中
0
会撑伞的猫先生
会撑伞的猫先生
有没有专业的测试android应用程序的测试工具?
0
一公斤梦想2
太罗嗦了  简单描述不行吗  
返回顶部
顶部