注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

网易杭州 QA Team

务实 专注 分享 做有态度的QA

 
 
 
 
 

日志

 
 

基于Instrumentation的android单元测试实践  

来自姜cong   2015-09-02 16:34:31|  分类: 移动APP |举报 |字号 订阅

  下载LOFTER 我的照片书  |
android的单元测试主要采用instrumentation,instrumentation是执行application instrumentation的基类,它具有启动能力,用于监控其他类的工具类。本博文在一个简单android demo开发应用上,使用instrumentation类完成单元测试。

android demo
MainActivity(具体代码见最后)
待测函数:
add():加法函数,不显示在ui上
sub():减法函数,不显示在ui上
changetextview():改变textview文字显示,通过监听button点击相应改变textview文本内容
multip():乘法函数,通过监听button点击相应,完成乘数和被乘数的获取,并将结果显示在ui控件上。
SampleTest(具体代码见最后)
代码简单说明:
  • 类继承:
 sampleTest继承InstrumentationTestCase,作为监控的具体实现的定制类
public class sampleTest extends InstrumentationTestCase {
private MainActivity sample = null;
  • 启动被测应用/被测类:
sampleTest继承InstrumentationTestCase,可以使用getInstrumentation()函数获取Instrumentation对象,通过Instrumentation的startActivitySync()函数启动一个Activity,直到Activity启动后返,其中intent设置被启动的Activity
Intent intent = new Intent();
intent.setClassName("com.example.jc.instrumentsample", MainActivity.class.getName());
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
sample = (MainActivity)getInstrumentation().startActivitySync(intent);
  • 单元case的编写:
  1. 函数名:测试函数以test为key命名
  2. 函数逻辑:点击按钮,改变textview文本显示。具体细节:为了防止ui线程停顿/卡死,新建一个线程来完成测试行为,即PerFromClick(继承runnable),其中函数中的btn2.performClick函数为模拟ui上点击行为
  3. 验证:获取textview的文本,调用assertEquals来验证与期望是否一致
  4. public void testActivity(){
    Log.d("testActivity","testActivity");
    SystemClock.sleep(1500);
    getInstrumentation().runOnMainSync(new PerFromClick(btn));
    SystemClock.sleep(1500);
    assertEquals("hello andriod",textView.getText().toString());
    }
    private class PerFromClick implements Runnable {
    Button btn2;
    public PerFromClick(Button button){
    btn2 = button;
    }
    @Override
    public void run() {
    btn2.performClick();
    }
    }
AndroidManifest.xml配置:
额外配置:
uses-library:使用的libraray配置
instrumentation:申明测试包名,单元测试的方式
<uses-library android:name="android.test.runner" />
<instrumentation android:targetPackage="com.example.jc.instrumentsample" android:name="android.test.InstrumentationTestRunner" />
测试执行:
build工程后,在终端输入命令:

$ adb shell am instrument -w com.example.jc.instrumentsample/android.test.InstrumentationTestRunner

com.example.jc.instrumentsample:包名

android.test.InstrumentationTestRunner:指明启动的单元测试类


运行结果:

执行命令后,会自动启动测试程序进行测试,测试结果会在终端显示。

单元测试一共执行了4个用例,其中3个失败(标红,失败的用力会有简单的log日志),1个通过(绿点,通过用例为点表示)

com.example.jc.instrumentsample.sampleTest:

Failure in testActivity

junit.framework.ComparisonFailure: expected:<[hello andrio]d> but was:<[this is my first androi]d>

     at com.example.jc.instrumentsample.sampleTest.testActivity(sampleTest.java:84)

     at java.lang.reflect.Method.invokeNative(Native Method)

     at android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:214)

     at android.test.InstrumentationTestCase.runTest(InstrumentationTestCase.java:199)

     at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:191)

     at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:176)

     at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:554)

     at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1701

 

Failure in testAdd:

junit.framework.AssertionFailedError: expected:<3> but was:<2>

     at com.example.jc.instrumentsample.sampleTest.testAdd(sampleTest.java:102)

     at java.lang.reflect.Method.invokeNative(Native Method)

     at android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:214)

     at android.test.InstrumentationTestCase.runTest(InstrumentationTestCase.java:199)

     at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:191

     at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:176

     at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:554)

     at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1701)

.

 

Failure in testSub:

junit.framework.AssertionFailedError: expected:<1> but was:<-1>

     at com.example.jc.instrumentsample.sampleTest.testSub(sampleTest.java:109)

     at java.lang.reflect.Method.invokeNative(Native Method)

     at android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:214)

     at android.test.InstrumentationTestCase.runTest(InstrumentationTestCase.java:199)

     at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:191)

     at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:176)

     at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:554)

     at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1701)

Test results for InstrumentationTestRunner=.F.F..

Time: 6.338

FAILURES!!!

Tests run: 4,  Failures: 3,  Errors: 0


以下为源码,可参考:

MainActivity代码
package com.example.jc.instrumentsample;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends Activity implements View.OnClickListener {

private Button btn;
private TextView tv;
private EditText num1;
private EditText num2;
private EditText rs;
private Button mult;


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (Button) findViewById(R.id.button_change);
btn.setOnClickListener(this);
tv = (TextView) findViewById(R.id.textView_hello);

num1 =(EditText)findViewById(R.id.editText_num1);
num2 =(EditText)findViewById(R.id.editText_num2);
rs = (EditText)findViewById(R.id.editText_rs);
mult = (Button)findViewById(R.id.button_multip);

mult.setOnClickListener(this);
}

@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.button_change:
changeTextView();
break;
case R.id.button_multip:
computeMultip();
default:
break;
}
}

//乘法
private void computeMultip() {
double n1 = Double.parseDouble(num1.getText().toString());
double n2 = Double.parseDouble(num2.getText().toString());
double res = n1*n2;
rs.setText(String.valueOf(res));
}

// textView变换
private void changeTextView() {tv.setText("this is my first android");}

// 加法
public int add(int a, int b) {return a + b;}

//减法
public int sub(int a, int b) {return b - a;}


}
sampleTest
package com.example.jc.instrumentsample;

import android.content.Intent;
import android.os.SystemClock;
import android.test.InstrumentationTestCase;
import android.util.Log;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

/**
* Created by jc on 15/9/1.
*/
public class sampleTest extends InstrumentationTestCase {
private MainActivity sample = null;
private Button btn = null;
private TextView textView = null;
private EditText num1 = null;
private EditText num2 = null;
private EditText rs = null;
private Button mult = null;

@Override
protected void setUp() throws Exception {
try {
Log.d("1111","111");
super.setUp();
}catch (Exception e){
e.printStackTrace();
}
Intent intent = new Intent();
intent.setClassName("com.example.jc.instrumentsample", MainActivity.class.getName());
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
sample = (MainActivity)getInstrumentation().startActivitySync(intent);
btn = (Button)sample.findViewById(R.id.button_change);
textView = (TextView)sample.findViewById(R.id.textView_hello);
num1 = (EditText)sample.findViewById(R.id.editText_num1);
num2 = (EditText)sample.findViewById(R.id.editText_num2);
rs = (EditText)sample.findViewById(R.id.editText_rs);
mult = (Button)sample.findViewById(R.id.button_multip);

}

@Override
protected void tearDown() throws Exception {
sample.finish();
try {
super.tearDown();
}catch (Exception e){
e.printStackTrace();
}
}

public void testMultip(){
SystemClock.sleep(1000);
getInstrumentation().runOnMainSync(new PerFromClickMultip(mult));
SystemClock.sleep(1000);
assertEquals("210.0", rs.getText().toString());
}

private class PerFromClickMultip implements Runnable {
private Button m = null;
public PerFromClickMultip(Button mult) {
m = mult;
}

@Override
public void run() {
num1.setText(String.valueOf(21));
num2.setText(String.valueOf(10));

double n1 = Double.parseDouble(num1.getText().toString());
double n2 = Double.parseDouble(num2.getText().toString());
double n3 = n1* n2;
rs.setText(String.valueOf(n3));
}
}

public void testActivity(){
Log.d("testActivity","testActivity");
SystemClock.sleep(1500);
getInstrumentation().runOnMainSync(new PerFromClick(btn));
SystemClock.sleep(1500);
assertEquals("hello andriod",textView.getText().toString());
}
private class PerFromClick implements Runnable {
Button btn2;
public PerFromClick(Button button){
btn2 = button;
}
@Override
public void run() {
btn2.performClick();
}
}


public void testAdd(){
String tag = "testAdd";
Log.d("testActivity","testAdd");
int test = sample.add(1,1);
assertEquals(3,test);
}

public void testSub(){
String tag = "testSub";
Log.d("testActivity","testAdd");
int test = sample.sub(2,1);
assertEquals(1,test);
}


}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.jc.instrumentsample">

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<uses-library android:name="android.test.runner" />
<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>
</application>
<instrumentation
android:name="android.test.InstrumentationTestRunner"
android:targetPackage="com.example.jc.instrumentsample" />
</manifest>






  评论这张
 
阅读(328)| 评论(3)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2016