只需apk的robotium安卓自动化测试入门--从第一个工程开始

一、关于安卓自动化测试

关于测试自动化金字塔,金字塔底端是最基础的单元测试,再往上是系统接口测试,再往上就是UI自动化测试。UI自动化测试能够按照写好的用例在机器上模拟用户操作实现一系列复杂的操作过程,能够极大地解放QA的工作量,特别是在回归验证以及安卓兼容性测试方面意义较大。所以,UI自动化测试方法还是一个QA需要掌握基本的技能之一。对于安卓UI自动化测试来说,常用的框架有MonkeyRunner、Robotium、uiautomation、Appium等,其中Roboitium是较为常用的框架之一,我们就从Robotium开始学习吧。(之前用的orange框架,发现公司里基本都不用这个框架了,没人维护,于是便转向基础的Robotium框架学习,重构自动化代码)。Robotium框架可以在无需源码仅有apk的情况下进行测试。

二、Robotium自动化测试的原理

Robotium是基于instrumentation的二次封装。Roboiutm分查找控件和点击控件两大类操作。查找控件的原理是:在waitter的waitForView()方法里面通过java反射获得视图,并匹配所需要的控件,查找并返回控件对象。点击控件的原理是:查找到的控件对象解析包装成MotionEvent,基于Instrumentation框架,通过InputManager注入事件。调用类组织结构如下图简示:


Robotium自动化原理简图

三、第一个Robotium自动化工程

话不多说,开始Robotium自动化测试工程吧!

环境准备:
操作系统:windows
android SDK
IDE:eclipse+ADT插件
不需源码,只要一个apk作为被测对象。(需要打包apk时生成的R文件)这里我们用网易云阅读的apk作为被测对象。

3.1 apk重命名&安装被测应用

Robotium框架需要被测应用和测试工程需要使用相同的签名,这样才可以使用Instrumentation把被测应用启动起来。我们本机eclipse使用的签名文件可以从window-> Preferences->Android->Build中查看,一般情况下一般存放于C:\Users\yourUserName.android目录下。如下图所示:


从图中看来我的Eclipse工程使用的是C盘下的debug.keystore文件,那么需要将被测apk用此keystore文件重签名然后装到真机或者测试机上就OK了。
重签名可使用重签名工具re-sign.jar

3.2 新建Robotium自动化测试工程

1.新建工程
在Eclipse上点击File->New->Other->Android->Android Test Project,命名后点击Next,Test Target选择“This Project”,然后点Next直至Finish为止。注:可能有时候会出现Eclipse报Null Pointer Exception错误,解决方案可参考

2.添加Robotium Jar包
右键该项目,选择property然后选择java build path, 选择 Add External JARs,选择下到的robotium-solo-5.1.jar。(注:Robotium可从网上下载Jar包)

3.新建测试用例
在项目下新建一个package,在package下新建一个测试类,该类继承自ActivityInstrumentationTestCase2。如下图简示:



注意到这里我新建了另一个package,里面只放了R.java文件,不能与测试文件放在同一个package下(会报错)。而com.pris.test这个package下新建了一个测试类FirstTestCase。FirstTestCase.java的代码如下:

package com.pris.test;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.robotium.solo.Solo;

import android.app.Instrumentation;
import android.content.Intent;
import android.test.ActivityInstrumentationTestCase2;
import android.view.View;
import android.widget.Button;
import junit.framework.Assert;
import other.R;

@SuppressWarnings("rawtypes")
public class FirstTestCase extends ActivityInstrumentationTestCase2 {

    private static final String TARGET_PACKAGE_ID = "com.netease.pris";
    private static final String LAUNCHER_ACTIVITY_FULL_CLASSNAME = "com.netease.pris.activity.MainGridActivity";
    private static Class launcherActivityClass;
    
    private Solo solo;
    static {
        try {
            launcherActivityClass = Class.forName(LAUNCHER_ACTIVITY_FULL_CLASSNAME);
            } catch (ClassNotFoundException e){
              throw new RuntimeException(e);
            }
       }
    
    @SuppressWarnings({ "unchecked", "deprecation" })
    public FirstTestCase(){
        super(TARGET_PACKAGE_ID,launcherActivityClass);
    }
    
    @Before 
    protected void setUp() throws Exception {
        super.setUp();
        /*第一套初始化方法,适用于主界面就是MainActivity的情况,只要下面一行代码就可以
          this.solo = new Solo(getInstrumentation(), getActivity());*/
        //第二套初始化方法,适用于主界面不是MainActivity的情况,使用Intent打开应用程序主界面
        Instrumentation instrumentation = getInstrumentation();
        this.solo = new Solo(instrumentation); 
        final String targetPackage = instrumentation.getTargetContext()
                .getPackageName();

        Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.setClassName(targetPackage,
                "com.netease.pris.activity.MainGridActivity");
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        instrumentation.getTargetContext().startActivity(intent);   
    }

    @Test
    public void testLogin() {
        boolean isOk = solo.waitForActivity("com.netease.pris.activity.MainGridActivity", 5000);
        Assert.assertTrue("没有调起应用", isOk);
        solo.sleep(3000);
        //进入左栏账号页面
        boolean isFindAccountButton = solo.waitForView(R.id.account_btn, 1, 2000);
        Assert.assertTrue("没有找到账号控件", isFindAccountButton);
        View account_button = solo.getView(R.id.account_btn);
        solo.clickOnView(account_button);
       //点击登陆按钮,打开登陆页面
        boolean isLoginButton = solo.waitForView(R.id.button_login, 1, 2000);
        Assert.assertTrue("没有找到登陆控件", isLoginButton);
    }

    @After
    public void tearDown() throws Exception {
        solo.finishOpenedActivities();
    }

代码结构较简单,包括一些静态资源,一个构造函数,一个solo初始化方法,一个核心的测试方法,最后一个销毁solo对象的结束方法。这里需要强调的是solo初始化setUp方法。有两套初始化方法,分别适用于主界面是否就是MainActivity的情况。这里我用的网易云阅读的apk进行测试,它的MainActivity是SplashActivity(是一个广告页),没有广告或者广告播放结束后进入主界面,所以直接写solo = new Solo(instrumentation,activity)的话是无法正确创建solo对象的。需要用Intent去打开应用程序主界面。然后solo对象的话使用solo = new(instrumentation)构造方法创建。

4.修改Manifest.xml文件
主要修改的地方是instrumentation中指定TargetPackage为待测试的包名,此外检查manifest中的package是否就是本测试工程的包名。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.pris.test"            //这里需是本测试工程的包名
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-sdk android:minSdkVersion="7" />

    <instrumentation
        android:name="android.test.InstrumentationTestRunner"
        android:targetPackage="com.netease.pris" />   //这里是被测应用程序的包名

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <uses-library android:name="android.test.runner" />
    </application>
</manifest>

5.执行测试用例
在测试用例文件上右击,选择run as Android Junit Test,就可以进行测试了。运行结束,在Eclipse左右会显示运行结果。如果出错,可以去查看logcat,排查错误的原因。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容