- 浏览: 1151376 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
MyEyeOfJava:
产生问题的主要原因:1.方洪波与南枫公司的直接主管李琼在合作共 ...
人力资源管理案例-左右为难的经理 -
吾名长弓:
学习了,作为一个管理新手,从文章里学到了很多东西,感谢 ...
2018新年管理感言 -
MyEyeOfJava:
非常不错,看过很多文章,说到管理者必然不能抛弃技术,我的主张是 ...
IT行业技术部门人员架构设计 -
小灯笼:
JMeter测试从入门到精通网盘地址:https://pan. ...
LR与Jmeter相关资料 -
flying6071:
“(2)CERT.SF:这是对摘要的签名文件。对前一步生成的M ...
Android签名与认证详细分析之一(CERT.RSA剖析)
android源代码中每个app下中都自带了一个test用例,下面主要介绍下camra单元测试用例
在AndroidManifest.xml中标明了测试用例instrumentation函数入口
Java代码
camera启动性能测试
Java代码
camera拍照压力测试,参数设定为反复拍照100次
Java代码
camera拍照视频录制切换测试
Java代码
如果想在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:
Java代码
Step 2.
接下来编写测试类,其中主要来测试add()方法。我们在当前代码目录下,在新建一个文件夹,命名为test,并在里面新建了包com.android.ut.test。然后往里面新增加一个class.具体如下:
Java代码
Step 3.最后一步就是要改一下Manifest文件。
Java代码
需要注意的是,在这里面我加上了:
Java代码
以及:
Java代码
Step 4.运行
首先通过模拟器运行一下AndroidUT,然后在命令行终端中运行
Java代码
这样你就可以看到测试结果了。
Java代码
com.cn.test.TestApp:..
Test results for InstrumentationTestRunner=..
Time: 2.866
OK (2 tests)
后台测试log日志信息
Java代码
(二) 转
任何程序的开发都离不开单元测试来保证其健壮和稳定。Android的程序自然也不例外。从Android SDK 0.9开始,就有了比较成熟的测试框架,但是直到目前最新的1.1版本,也没有详细的文档介绍这个内容,只是简单的给了一个Api Demos里的几个单元测试代码。因此,我在这里对此内容做一下梳理和总结: JUnit还能用么?
在Java下做单元测试必然用到JUnit。这里说的JUnit是指从Apache基金会下载的junit.jar里提供的一系列单元测试功能。这些功能显然是运行在JDK之上的。在Android下已经没有了JDK,自然也无法运行JUnit。但是这并不妨碍我们利用JUnit编写单元测试。只不过在运行单元测试时,一定要用JDK来运行,利用java命令来启动JUnit的某个Runner。如果是用Eclipse的话,可以在Run Configuration里新建一个JUnit。但是一定要记得在Classpath选项卡里将Bootstrap Entries中的Android Library改成JRE,并且添加junit.jar。
很明显的,这种测试就是正规的Java单元测试,和Android没有任何关系。你无法测试任何关于Android系统中的API,你写的Activity,人机界面等等。所以,如果你想测试仅仅是一些封装数据的对象,或者是纯粹的数值计算,还是可以用这种方法的。 Android里面的junit.framework包是怎么回事?
很多人看到这个包的时候,第一反应是Android是不是已经完整集成了JUnit。很遗憾这不是事实。如果你按照JUnit的运行方法,却不像上面那样改用JDK,就一定会得到一个异常:
Java代码
实际上,TestCase这个类用于在Android担当所有独特的TestCase的基类的作用,它是一个Abstract Class。Android单元测试类继承关系图如下所示:
之所以有那么多XXXTestCase主要是为了简化工作。例如当你想对一个访问数据库的功能进行测试时,首先需要自己启动并初始化数据库。在这里是类似的,如果你想测试一个Activity,首先要启动它。而ActivityTestCase就会自动帮你做完这些事情。而 ActivityUnitTestCase会更注重测试的独立性,它会让测试与Android底层的联系降到最低。其余的类可以查看相关的Javadoc 来按需挑选。要编写测试,就是找到合适的XXXTestCase作为基类来继承,并且编写自己的测试方法。
很明显的,最简单的编写测试的方法就是继承AndroidTestCase写一个自己的TestCase。然后为自己的一组 TestCase写一个Activity界面,由界面控制TestCase的启动,运行和结果报告。但是,你很快会发现,为何要给测试写一个界面呢?这太诡异了。这时就需要一种技术,它可以利用命令行(Shell)来启动一组测试,并且通过命令行的形式给出结果。这就是所谓的 Instrumentation。 什么是Instrumentation?
一般在开发Android程序的时候,需要写一个manifest文件,其结构是:
Java代码
这样,在启动程序的时候就会先启动一个Application,然后在此Application运行过程中根据情况加载相应的 Activity,而Activity是需要一个界面的。但是Instrumentation并不是这样的。你可以将Instrumentation理解为一种没有图形界面的,具有启动能力的,用于监控其他类(用Target Package声明)的工具类。任何想成为Instrumentation的类必须继承android.app.Instrumentation。下面是这个类的解释:
Base class for implementing application instrumentation code. When running with instrumentation turned on, this class will be instantiated for you before any of the application code, allowing you to monitor all of the interaction the system has with the application. An Instrumentation implementation is described to the system through an AndroidManifest.xml's <instrumentation> tag.
对于单元测试,我们需要认真了解的就是android.test.InstrumentationTestRunner类。这是Android单元测试的主入口。它相当于JUnit当中TestRunner的作用。
那么如何加载它呢,首先要在manifest文件中加入一行关于Instrumentation的声明。比如Android Api Demos中的测试里的manifest是这么写的(我滤掉了所有的注释):
Java代码
如果用Eclipse的ADT插件(0.8版本以上),也可以用图形界面来添加,如下图:
编辑好manifest,就可以打包(build,可以用Eclipse ADT来做,也可以用aapt命令手工完成),然后安装到虚拟机上(用adb install命令)。之后就可以利用命令行的方式来加载你的单元测试了。在Android Shell中加载一个Instrumentation的方法是利用以下命令:
Java代码
adb shell am instrument –w XXXXXX
其中-w是指定Instrumentation类的参数标志。一个简单的例子是:
Java代码
当然,也可以利用adb shell先进入android命令行模式,再直接写am instrument –w XXXXXXX。下面将具体介绍如何将根据需要加载一组单元测试。 如何在Android中利用Instrumentation来进行测试?
在介绍具体的命令之前,我们先理解一下单元测试的层次。一组单元测试可以被组织成若干个TestSuite。每个TestSuite包含若干TestCase(某个继承android.jar的junit.framework.TestCase的类)。每个TestCase又包含若干个 Test(具体的test方法)。
如果假设com.android.foo是你的测试代码的包的根。当执行以下命令时,会执行所有的TestCase的所有Test。测试的对象就是在Target Package中指定的包中的代码:
Java代码
adb shell am instrument -w com.android.foo/android.test.InstrumentationTestRunner
如果你想运行一个TestSuite,首先继承android.jar的junit.framework.TestSuite类,实现一个TestSuite(比如叫com.android.foo.MyTestSuite),然后执行以下命令执行此TestSuite
Java代码
其中的-e表示额外的参数,语法为-e [arg1] [value1] [arg2] [value2] …这里用到了class参数。
如果仅仅想运行一个TestCase(比如叫com.android.foo.MyTestCase),则用以下命令:
Java代码
如果仅仅想运行一个Test(比如就是上面MyTestCase的testFoo方法),很类似的,就这样写:
Java代码
然后,所有的测试结果会输出到控制台,并会做一系列统计,如标记为E的是Error,标记为F的是Failure,Success的测试则会标记为一个点。这和JUnit的语义一致。如果希望断点调试你的测试,只需要直接在代码上加上断点,然后将运行命令参数的-e后边附加上debug true后运行即可。更加详细的内容可以看InstrumentationTestRunner的Javadoc。我希望Android能尽快有正式的文档来介绍这个内容。 如何在Android的单元测试中做标记?
在android.test.annotation包里定义了几个annotation,包括 @LargeTest,@MediumTest,@SmallTest,@Smoke,和@Suppress。你可以根据自己的需要用这些 annotation来对自己的测试分类。在执行单元测试命令时,可以在-e参数后设置“size large”/ “size medium”/ “size small”来执行具有相应标记的测试。特别的@Supperss可以取消被标记的Test的执行。 完整的操作过程
总结以上所有的内容,编写并运行完整的测试需要以下的步骤:
以上步骤中,在Android自带的例子中,我发现它有两个manifest.xml。也就是说在步骤3中源代码和测试代码分别生成了两个不同的包。然后步骤4利用adb install命令安装到了虚拟机上。由于我没有找到Eclipse ADT有办法可以为一个只有Instrumentation,没有Activity的Application打包并安装,于是采用了略微不同的办法完成了这个工作。下面将一一详细介绍整个过程。 1. 编写程序
我新建了一个项目TestApp,参数为:
Java代码
其中,我故意将减法的a – b写成了b – a。 2. 编写测试程序
然后,我新建了一个Source Folder,名为test,并在里面新建了包com.android.testapp.test。并定义了一个TestCase,名为TestMainActivity,源代码如下:
Java代码
我继承了ActivityInstrumentationTestCase。这个TestCase在执行时会自动帮我启动相应的Activity。
接下来就是程序的Manifest:
Java代码
在这个文件中,我将Activity和Instrumentation的声明写到了一起,而没有像Apis Demo那样分开。请注意里面的<uses-library>标签。如果没有那句,在运行测试时会报告找不到TestRunner。这是由于 Android在build的时候只把需要的东西打包,所以你必须明确的告诉Android Builder这一点。 3. Build和Install
在Eclipse上,这两个步骤是一起完成的。只要点一下Run即可。只不过如果你不在Run Configuration里将安装后的Launch Action设为“Do Nothing”,就会自动运行一下你的MainActivity。对于我们,设为Do Nothing即可。如下图:
完成后,利用命令
Java代码
可以在已经安装的pkg列表里看到com.android.testapp。 4. 运行测试,查看结果
之后就打开命令行,运行以下命令
Java代码
即可看到如下的结果:
可以看到,单元测试正确的找到了减法中的错误。结果中的成功的测试显示为”.”,一个失败的显示为”F”。只不过我还是不太理解为什么我只写了两个测试方法,Tests run却显示了3。
(三) 转
Android下使用JUnit
Andorid下使用Junit测试框架,是步入正规的Androdid开发的必经之路,在Junit中可以得到组件,可以模拟发送事件,检测程序处理的正确性,下面就开始我们的教程:
工具:
1、Android1.5 SDK
2、ADT 0.9
3、Eclipse
需要的知识:
1、 Android开发的基础
2、Junit的基础
一、
首先建立工程:
目录:
选中的test source folder是测试类的包,包名随便,但是在配置Manifest.xml要注意
二、配置\layout\main.xml文件,加入两个button组件,代码如下:
Java代码
三、被测试的Activity代码
Java代码
四、测试NewActivity代码,这里要继承ActivityInstrumentationTestCase2,ActivityInstrumentationTestCase2是TestCase的子类
Java代码
* package cc.andoridos.activity.test;
五、配置Manifest.xml文件
Java代码
Java代码
# E:\android\android-sdk-windows-1.5_pre\tools>adb shell am instrument -w cc.andro
# idos.activity/android.test.InstrumentationTestRunner
# 如果你配置了Android环境变量,直接使用:
# adb shell am instrument -w cc.androidos.activity/android.test.InstrumentationTestRunner
# 语法:adb shell am instrument -w <被测试的类的包名>/android.test.InstrumentationTestRunner
此篇引用原文地址:http://mintelong.iteye.com/blog/460903,尊重作者以及版权
在AndroidManifest.xml中标明了测试用例instrumentation函数入口
Java代码
<?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启动性能测试
Java代码
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次
Java代码
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); } }
camera拍照视频录制切换测试
Java代码
package com.android.camera.stress; import com.android.camera.VideoCamera; 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.SwitchPreview \ * -w com.android.camera.tests/com.android.camera.CameraStressTestRunner * */ public class SwitchPreview extends ActivityInstrumentationTestCase2 <VideoCamera>{ private String TAG = "SwitchPreview"; private static final int TOTAL_NUMBER_OF_SWITCHING = 200; private static final long WAIT_FOR_PREVIEW = 2000; public SwitchPreview() { super("com.android.camera", VideoCamera.class); } @Override protected void setUp() throws Exception { getActivity(); super.setUp(); } @Override protected void tearDown() throws Exception { getActivity().finish(); super.tearDown(); } @LargeTest public void testSwitchMode() { //Switching the video and the video recorder mode Instrumentation inst = getInstrumentation(); try{ for (int i=0; i< TOTAL_NUMBER_OF_SWITCHING; i++) { Thread.sleep(WAIT_FOR_PREVIEW); inst.sendKeyDownUpSync(KeyEvent.KEYCODE_MENU); inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_LEFT); inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER); Thread.sleep(WAIT_FOR_PREVIEW); } } catch (Exception e){ Log.v(TAG, e.toString()); } assertTrue("testSwitchMode",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:
Java代码
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.具体如下:
Java代码
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文件。
Java代码
<?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>
需要注意的是,在这里面我加上了:
Java代码
<uses-library android:name="android.test.runner" />
以及:
Java代码
<instrumentation android:targetPackage="com.android.ut" android:name="android.test.InstrumentationTestRunner" android:label="Test Unit Tests"></instrumentation>
Step 4.运行
首先通过模拟器运行一下AndroidUT,然后在命令行终端中运行
Java代码
adb shell am instrument -e class com.android.ut.test.TestApp -wcom.android.ut/android.test.InstrumentationTestRunner
这样你就可以看到测试结果了。
Java代码
# 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日志信息
Java代码
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
(二) 转
任何程序的开发都离不开单元测试来保证其健壮和稳定。Android的程序自然也不例外。从Android SDK 0.9开始,就有了比较成熟的测试框架,但是直到目前最新的1.1版本,也没有详细的文档介绍这个内容,只是简单的给了一个Api Demos里的几个单元测试代码。因此,我在这里对此内容做一下梳理和总结: JUnit还能用么?
在Java下做单元测试必然用到JUnit。这里说的JUnit是指从Apache基金会下载的junit.jar里提供的一系列单元测试功能。这些功能显然是运行在JDK之上的。在Android下已经没有了JDK,自然也无法运行JUnit。但是这并不妨碍我们利用JUnit编写单元测试。只不过在运行单元测试时,一定要用JDK来运行,利用java命令来启动JUnit的某个Runner。如果是用Eclipse的话,可以在Run Configuration里新建一个JUnit。但是一定要记得在Classpath选项卡里将Bootstrap Entries中的Android Library改成JRE,并且添加junit.jar。
很明显的,这种测试就是正规的Java单元测试,和Android没有任何关系。你无法测试任何关于Android系统中的API,你写的Activity,人机界面等等。所以,如果你想测试仅仅是一些封装数据的对象,或者是纯粹的数值计算,还是可以用这种方法的。 Android里面的junit.framework包是怎么回事?
很多人看到这个包的时候,第一反应是Android是不是已经完整集成了JUnit。很遗憾这不是事实。如果你按照JUnit的运行方法,却不像上面那样改用JDK,就一定会得到一个异常:
Java代码
# # An unexpected error has been detected by Java Runtime Environment: # # Internal Error (classFileParser.cpp:2924), pid=4900, tid=4476 #Error: ShouldNotReachHere() # # Java VM: Java HotSpot(TM) Client VM (10.0-b19 mixed mode windows-x86) # An error report file with more information is saved as: # E:\Mydoc\EclipseWorkspace\TestAndroid\hs_err_pid4900.log # # If you would like to submit a bug report, please visit: # http://java.sun.com/webapps/bugreport/crash.jsp #
实际上,TestCase这个类用于在Android担当所有独特的TestCase的基类的作用,它是一个Abstract Class。Android单元测试类继承关系图如下所示:
之所以有那么多XXXTestCase主要是为了简化工作。例如当你想对一个访问数据库的功能进行测试时,首先需要自己启动并初始化数据库。在这里是类似的,如果你想测试一个Activity,首先要启动它。而ActivityTestCase就会自动帮你做完这些事情。而 ActivityUnitTestCase会更注重测试的独立性,它会让测试与Android底层的联系降到最低。其余的类可以查看相关的Javadoc 来按需挑选。要编写测试,就是找到合适的XXXTestCase作为基类来继承,并且编写自己的测试方法。
很明显的,最简单的编写测试的方法就是继承AndroidTestCase写一个自己的TestCase。然后为自己的一组 TestCase写一个Activity界面,由界面控制TestCase的启动,运行和结果报告。但是,你很快会发现,为何要给测试写一个界面呢?这太诡异了。这时就需要一种技术,它可以利用命令行(Shell)来启动一组测试,并且通过命令行的形式给出结果。这就是所谓的 Instrumentation。 什么是Instrumentation?
一般在开发Android程序的时候,需要写一个manifest文件,其结构是:
Java代码
<application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".TestApp" android:label="@string/app_name"> …… </activity> </application>
这样,在启动程序的时候就会先启动一个Application,然后在此Application运行过程中根据情况加载相应的 Activity,而Activity是需要一个界面的。但是Instrumentation并不是这样的。你可以将Instrumentation理解为一种没有图形界面的,具有启动能力的,用于监控其他类(用Target Package声明)的工具类。任何想成为Instrumentation的类必须继承android.app.Instrumentation。下面是这个类的解释:
Base class for implementing application instrumentation code. When running with instrumentation turned on, this class will be instantiated for you before any of the application code, allowing you to monitor all of the interaction the system has with the application. An Instrumentation implementation is described to the system through an AndroidManifest.xml's <instrumentation> tag.
对于单元测试,我们需要认真了解的就是android.test.InstrumentationTestRunner类。这是Android单元测试的主入口。它相当于JUnit当中TestRunner的作用。
那么如何加载它呢,首先要在manifest文件中加入一行关于Instrumentation的声明。比如Android Api Demos中的测试里的manifest是这么写的(我滤掉了所有的注释):
Java代码
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.android.apis.tests"> <application> <uses-library android:name="android.test.runner" /> </application> <instrumentation android:name="android.test.InstrumentationTestRunner" android:targetPackage="com.example.android.apis" android:label="Tests for Api Demos."/> </manifest>
如果用Eclipse的ADT插件(0.8版本以上),也可以用图形界面来添加,如下图:
编辑好manifest,就可以打包(build,可以用Eclipse ADT来做,也可以用aapt命令手工完成),然后安装到虚拟机上(用adb install命令)。之后就可以利用命令行的方式来加载你的单元测试了。在Android Shell中加载一个Instrumentation的方法是利用以下命令:
Java代码
adb shell am instrument –w XXXXXX
其中-w是指定Instrumentation类的参数标志。一个简单的例子是:
Java代码
adb shell am instrument -w com.android.foo/android.test.InstrumentationTestRunner
当然,也可以利用adb shell先进入android命令行模式,再直接写am instrument –w XXXXXXX。下面将具体介绍如何将根据需要加载一组单元测试。 如何在Android中利用Instrumentation来进行测试?
在介绍具体的命令之前,我们先理解一下单元测试的层次。一组单元测试可以被组织成若干个TestSuite。每个TestSuite包含若干TestCase(某个继承android.jar的junit.framework.TestCase的类)。每个TestCase又包含若干个 Test(具体的test方法)。
如果假设com.android.foo是你的测试代码的包的根。当执行以下命令时,会执行所有的TestCase的所有Test。测试的对象就是在Target Package中指定的包中的代码:
Java代码
adb shell am instrument -w com.android.foo/android.test.InstrumentationTestRunner
如果你想运行一个TestSuite,首先继承android.jar的junit.framework.TestSuite类,实现一个TestSuite(比如叫com.android.foo.MyTestSuite),然后执行以下命令执行此TestSuite
Java代码
adb shell am instrument -e class com.android.foo.MyTestSuite -w com.android.foo/android.test.InstrumentationTestRunner
其中的-e表示额外的参数,语法为-e [arg1] [value1] [arg2] [value2] …这里用到了class参数。
如果仅仅想运行一个TestCase(比如叫com.android.foo.MyTestCase),则用以下命令:
Java代码
adb shell am instrument -e class com.android.foo.MyTestCase -w com.android.foo/android.test.InstrumentationTestRunner
如果仅仅想运行一个Test(比如就是上面MyTestCase的testFoo方法),很类似的,就这样写:
Java代码
adb shell am instrument -e class com.android.foo.MyTestCase#testFoo -w com.android.foo/android.test.InstrumentationTestRunner
然后,所有的测试结果会输出到控制台,并会做一系列统计,如标记为E的是Error,标记为F的是Failure,Success的测试则会标记为一个点。这和JUnit的语义一致。如果希望断点调试你的测试,只需要直接在代码上加上断点,然后将运行命令参数的-e后边附加上debug true后运行即可。更加详细的内容可以看InstrumentationTestRunner的Javadoc。我希望Android能尽快有正式的文档来介绍这个内容。 如何在Android的单元测试中做标记?
在android.test.annotation包里定义了几个annotation,包括 @LargeTest,@MediumTest,@SmallTest,@Smoke,和@Suppress。你可以根据自己的需要用这些 annotation来对自己的测试分类。在执行单元测试命令时,可以在-e参数后设置“size large”/ “size medium”/ “size small”来执行具有相应标记的测试。特别的@Supperss可以取消被标记的Test的执行。 完整的操作过程
总结以上所有的内容,编写并运行完整的测试需要以下的步骤:
以上步骤中,在Android自带的例子中,我发现它有两个manifest.xml。也就是说在步骤3中源代码和测试代码分别生成了两个不同的包。然后步骤4利用adb install命令安装到了虚拟机上。由于我没有找到Eclipse ADT有办法可以为一个只有Instrumentation,没有Activity的Application打包并安装,于是采用了略微不同的办法完成了这个工作。下面将一一详细介绍整个过程。 1. 编写程序
我新建了一个项目TestApp,参数为:
Java代码
Package Name: com.android.testapp Activity Name: MainActivity Application Name: TestApp 以下是MainActivity的源代码: package com.android.testapp; import android.app.Activity; import android.os.Bundle; public class MainActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } public int sum(int a, int b) { return a + b; } public int substract(int a, int b) { return b - a; } }
其中,我故意将减法的a – b写成了b – a。 2. 编写测试程序
然后,我新建了一个Source Folder,名为test,并在里面新建了包com.android.testapp.test。并定义了一个TestCase,名为TestMainActivity,源代码如下:
Java代码
package com.android.testapp.test; import com.android.testapp.MainActivity; import android.test.ActivityInstrumentationTestCase; import android.test.suitebuilder.annotation.MediumTest; public class TestMainActivity extends ActivityInstrumentationTestCase<MainActivity> { public TestMainActivity() { super("com.android.testapp", MainActivity.class); } public TestMainActivity(String pkg, Class<MainActivity> activityClass) { super(pkg, activityClass); } @MediumTest public void testSum() { assertEquals(3, getActivity().sum(1, 2)); } @MediumTest public void testSubstract() { assertEquals(-1, getActivity().substract(1, 2)); } }
我继承了ActivityInstrumentationTestCase。这个TestCase在执行时会自动帮我启动相应的Activity。
接下来就是程序的Manifest:
Java代码
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.testapp" android:versionCode="1" android:versionName="1.0.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".MainActivity" 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.testapp" android:name="android.test.InstrumentationTestRunner" android:label="Test Unit Tests"></instrumentation> </manifest>
在这个文件中,我将Activity和Instrumentation的声明写到了一起,而没有像Apis Demo那样分开。请注意里面的<uses-library>标签。如果没有那句,在运行测试时会报告找不到TestRunner。这是由于 Android在build的时候只把需要的东西打包,所以你必须明确的告诉Android Builder这一点。 3. Build和Install
在Eclipse上,这两个步骤是一起完成的。只要点一下Run即可。只不过如果你不在Run Configuration里将安装后的Launch Action设为“Do Nothing”,就会自动运行一下你的MainActivity。对于我们,设为Do Nothing即可。如下图:
完成后,利用命令
Java代码
adb shell pm list packages
可以在已经安装的pkg列表里看到com.android.testapp。 4. 运行测试,查看结果
之后就打开命令行,运行以下命令
Java代码
adb shell am instrument –e class com.android.testapp.test.TestMainActivity –w com.android.testapp/android.test.InstrumentationTestRunner
即可看到如下的结果:
可以看到,单元测试正确的找到了减法中的错误。结果中的成功的测试显示为”.”,一个失败的显示为”F”。只不过我还是不太理解为什么我只写了两个测试方法,Tests run却显示了3。
(三) 转
Android下使用JUnit
Andorid下使用Junit测试框架,是步入正规的Androdid开发的必经之路,在Junit中可以得到组件,可以模拟发送事件,检测程序处理的正确性,下面就开始我们的教程:
工具:
1、Android1.5 SDK
2、ADT 0.9
3、Eclipse
需要的知识:
1、 Android开发的基础
2、Junit的基础
一、
首先建立工程:
目录:
选中的test source folder是测试类的包,包名随便,但是在配置Manifest.xml要注意
二、配置\layout\main.xml文件,加入两个button组件,代码如下:
Java代码
* <?xml version="1.0" encoding="utf-8"?> * <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" * android:orientation="vertical" android:layout_width="fill_parent" * android:layout_height="fill_parent"> * <Button android:text="Button01" android:id="@+id/Button01" * android:layout_width="wrap_content" android:layout_height="wrap_content"></Button> * <Button android:text="Button02" android:id="@+id/Button02" * android:layout_width="wrap_content" android:layout_height="wrap_content"></Button> * </LinearLayout>
三、被测试的Activity代码
Java代码
# package cc.androidos.activity; # import android.app.Activity; # import android.os.Bundle; # import android.widget.Button; # public class NewActivity 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; # } # }
四、测试NewActivity代码,这里要继承ActivityInstrumentationTestCase2,ActivityInstrumentationTestCase2是TestCase的子类
Java代码
* package cc.andoridos.activity.test;
* import cc.androidos.activity.NewActivity; * import cc.androidos.activity.R; * import android.test.ActivityInstrumentationTestCase2; * import android.util.Log; * import android.view.KeyEvent; * import android.widget.Button; * public class TestNewActivity extends * ActivityInstrumentationTestCase2<NewActivity> { * private Button button1 = null; * private Button button2 = null; * private NewActivity newActivity = null; * public TestNewActivity() { * super("cc.androidos.activity", NewActivity.class); * //This first parameter should the Activity package * //if other , the junit give us the exception: unable resolve the activity * } * * @Override * protected void setUp() throws Exception { * String tag = "setUp"; * Log.e(tag, "init all var...."); * newActivity = getActivity(); * button1 = (Button) newActivity.findViewById(R.id.Button01); * button2 = (Button) newActivity.findViewById(R.id.Button02); * } * /** * * Testing the button is focused or not * */ * public void testButtonFocus() { * String tag = "testButtonFocus"; * Log.e(tag, "start the button focus..."); * assertTrue("Button1 is focused", button1.isFocused()); * Log.e(tag, "send the down key event..."); * sendKeys(KeyEvent.KEYCODE_DPAD_DOWN); * assertTrue("Button2 is focused", button2.isFocused()); * } * * /** * * Testing the add method in actvity * */ * public void testAdd(){ * String tag ="testAdd"; * Log.e(tag, "Test the add method in NewActivity..."); * int i = newActivity.add(2, 5); * assertEquals(7, i); * } * * }
五、配置Manifest.xml文件
Java代码
* <?xml version="1.0" encoding="utf-8"?> * <manifest xmlns:android="http://schemas.android.com/apk/res/android" * package="cc.androidos.activity" android:versionCode="1" * android:versionName="1.0"> * <application android:icon="@drawable/icon" android:label="@string/app_name"> * <activity android:name=".NewActivity" android:label="@string/app_name"> * <intent-filter> * <action android:name="android.intent.action.MAIN" /> * <category android:name="android.intent.category.LAUNCHER" /> * </intent-filter> * </activity> * <activity android:name=".NewActivity2" android:label="@string/app_name"> * </activity> * <uses-library android:name="android.test.runner" /> * <!-- Loading test library --> * </application> * <uses-sdk android:minSdkVersion="3" /> * * <!-- 这个是关键,android:targetPackage="cc.androidos.activity"要测试的包,android:name="android.test.InstrumentationTestRunner" 用于跑TestCase的类--> * <instrumentation android:targetPackage="cc.androidos.activity" * android:label="Test New Activty" android:name="android.test.InstrumentationTestRunner"></instrumentation> * </manifest>
Java代码
# E:\android\android-sdk-windows-1.5_pre\tools>adb shell am instrument -w cc.andro
# idos.activity/android.test.InstrumentationTestRunner
# 如果你配置了Android环境变量,直接使用:
# adb shell am instrument -w cc.androidos.activity/android.test.InstrumentationTestRunner
# 语法:adb shell am instrument -w <被测试的类的包名>/android.test.InstrumentationTestRunner
此篇引用原文地址:http://mintelong.iteye.com/blog/460903,尊重作者以及版权
发表评论
-
[ATC]Facebook开源弱网模拟工具
2016-03-26 14:24 2712需要注意如下:1.笔者使用了linux USB网卡,是让 ... -
【远程真机管理】openstf
2016-03-24 11:36 2926网站地址:https://github.com/ope ... -
AndroidStudio性能优化
2016-03-15 16:39 1146Android Studio慢、吃内存!启动时后会立即通过Gr ... -
Drozer使用手册
2016-01-18 15:22 2228Drozer ⼯具的安装与启动:源码地址(https:// ... -
TCPDUMP抓包
2015-12-17 20:56 782tcpdump 使用方法:唯有使用文章描述的参数移动手机的 ... -
HTML5安全
2015-10-30 19:43 1319移动安全问题汇总:htt ... -
Android插件DSL配置文档
2015-07-29 15:54 1024Android Plugin DSL Reference -
Gradle-Android打包文档
2015-07-29 15:29 1819http://tools.android.com/tech- ... -
Android性能优化典范(一)
2015-06-02 17:26 13142015年伊始,Google发布 ... -
Android性能系列-电量篇
2015-05-29 16:28 1344电量篇 1) Understanding Battery ... -
Android性能系列-内存篇
2015-05-29 16:27 823内存篇 1) Memory, GC, and Perfor ... -
Android性能系列-运算篇
2015-05-29 16:26 579运算篇 1) Intro to Compute ... -
Android性能系列-渲染篇
2015-05-29 16:25 835Google近期在Udacity上发布了Android性能优 ... -
如何通过wifi在android手机上安装调试应用
2015-05-29 14:42 7021. 首先还是要打开手机 ... -
[Android]解决android65K方法引用限制
2015-01-14 11:39 1623解决方案如下: 1.Google官方的andr ... -
[Android]获取整体APP CPU信息
2015-01-07 14:34 4790通过proc获取CPU信息。adb shell cat / ... -
genymotion-安卓模拟器-IMEI修改方法
2015-01-05 15:44 4416看淘宝动辄就几十元卖这么个破玩意儿,实在是懒得说什么了,人总 ... -
[android]创建固定大小文件
2014-12-29 19:27 2206dd if=/dev/zero of=yourfile ... -
[总结]无线测试
2014-12-18 16:33 1144本文主要介绍测试在项目的各个阶段应该要做的事情、使用的工具和 ... -
[适配性]移动Webapp自适应方案
2014-12-18 16:15 1870此次方案的优化点 页面元素会随宽度的变化而自适应的放大 ...
相关推荐
本实例聚焦于Android应用中的单元测试,特别是针对登录界面及其相关功能的测试。我们将探讨如何构建和执行这些测试,以及使用到的相关工具和技术。 首先,单元测试通常使用JUnit框架进行,这是Java开发中的标准测试...
使用uiautomator2+pytest+allure进行Android的UI自动化测试 测试携程旅行App,首页-机票-机票搜索模块 简介 使用uiautomator2+pytest+allure进行Android的UI自动化测试 环境搭建 pytest框架 pip install pytest ...
UIAutomator框架是Google为了简化和增强Android自动化测试体验而推出的一个工具。与基于Python的Monkey和MonkeyRunner等早期测试工具相比,UIAutomator提供了更丰富的事件操作支持。Monkey是Android SDK自带的测试...
在Android开发领域,UIAutomator是一款强大的自动化测试框架,它主要用来进行用户界面的UI测试。这个框架允许开发者编写测试脚本来验证应用的UI组件的行为和功能,确保应用在不同设备和Android版本上的表现一致性。...
1.Android 自动化测试1:启动app的默认Activity,启动指定Activity 2.Android 自动化测试2: 捕获Element,并定位Element,实现点击、拖、拽、按压等 3.Android 自动化测试3:验证Element,enabled、visible、exist等 4...
Android自动化测试工具和方法大大提升了测试效率,减少了手动测试的时间和人力成本。本文将深入探讨“Android自动化测试工具及方法”,并以“Robotium”为例,介绍如何对APK进行自动化测试。 一、Android自动化测试...
**Android自动化测试** 在软件开发领域,特别是移动应用开发中,测试是不可或缺的一环,而自动化测试能够极大地提高测试效率和质量。Android自动化测试就是利用特定的工具和框架,自动执行预先设定好的测试脚本,以...
### Android自动化测试_Monkeyrunner #### 搭建Android自动化测试环境 ##### 环境准备 在开始使用Monkeyrunner进行自动化测试之前,需要确保已经正确安装并配置了以下软件环境: 1. **JDK (Java Development Kit...
Robot Framework 是一款强大的自动化测试框架,支持多种平台和领域的测试,包括 Android、Web、iOS、接口和数据库测试。本篇文章将详细介绍如何搭建和使用 Robot Framework 的自动化测试环境。 首先,让我们从安装 ...
这个主题“App自动化实例(IOS+Android)”聚焦于如何在iOS和Android平台上实现自动化测试,特别是通过使用appium-1.6-XCUITest-demo和android-uiautomator-server这两个工具。 首先,我们来了解一下XCUITest。...
"Selenium2 Java自动化测试实战(修正版)12_05.pdf"可能包含了使用Java进行Selenium测试的实例和最佳实践,包括如何创建测试套件,如何处理各种元素交互,以及异常处理等。 接着,Robot Framework是一个通用的自动化...
项目的核心工具是APPIUM,一个广泛使用的跨平台移动自动化测试框架,支持Android和iOS应用的自动化。APPIUM允许测试工程师通过WebDriver协议与应用程序进行交互,使得测试脚本可以使用多种编程语言编写,如Java、...
Robotium是一个广泛应用于Android平台的自动化测试框架,它能够模拟用户的各种操作行为,包括但不限于点击、滑动、输入文本等,从而实现对应用功能的全面测试。然而,在面对多内核浏览器时,Robotium可能会遇到一些...
"自动化测试Demo"是一个专门针对Android平台的实例,它演示了如何利用Robotium5这一强大的自动化测试框架,对Android应用进行自动化的创建、编辑和删除操作。Robotium5是Android开发者们常用的一种UI测试工具,它...
"自动化测试最佳实践示例视频"这个标题表明我们即将探讨的是如何有效地运用自动化测试技术,并通过视频实例来展示这些最佳实践。下面我们将深入讲解自动化测试的核心概念、常用工具以及最佳实践策略。 自动化测试的...
Robotium是一款强大的自动化测试框架,专门用于Android应用的UI测试。本文将深入探讨如何利用Robotium来创建一个Android实例,以Calculator应用为例,进行详细的测试步骤解析。 首先,我们需要了解Robotium的基本...
本文将深入探讨手机自动化测试中的Appium框架,特别是在Android平台上的应用。Appium是一个开源的自动化测试工具,它允许开发者对原生、混合以及移动Web应用程序进行自动化测试。本资源包包含了Appium在Android环境...
基于Android的Appium+Python自动化脚本编写 在本文中,我们将详解基于Android的Appium+Python自动化脚本...基于Android的Appium+Python自动化脚本编写可以帮助我们自动化测试Android应用程序,提高测试效率和准确性。