只需apk的robotium安卓自動(dòng)化測(cè)試入門--從第一個(gè)工程開始

一、關(guān)于安卓自動(dòng)化測(cè)試

關(guān)于測(cè)試自動(dòng)化金字塔,金字塔底端是最基礎(chǔ)的單元測(cè)試,再往上是系統(tǒng)接口測(cè)試,再往上就是UI自動(dòng)化測(cè)試。UI自動(dòng)化測(cè)試能夠按照寫好的用例在機(jī)器上模擬用戶操作實(shí)現(xiàn)一系列復(fù)雜的操作過程,能夠極大地解放QA的工作量,特別是在回歸驗(yàn)證以及安卓兼容性測(cè)試方面意義較大。所以,UI自動(dòng)化測(cè)試方法還是一個(gè)QA需要掌握基本的技能之一。對(duì)于安卓UI自動(dòng)化測(cè)試來說,常用的框架有MonkeyRunner、Robotium、uiautomation、Appium等,其中Roboitium是較為常用的框架之一,我們就從Robotium開始學(xué)習(xí)吧。(之前用的orange框架,發(fā)現(xiàn)公司里基本都不用這個(gè)框架了,沒人維護(hù),于是便轉(zhuǎn)向基礎(chǔ)的Robotium框架學(xué)習(xí),重構(gòu)自動(dòng)化代碼)。Robotium框架可以在無需源碼僅有apk的情況下進(jìn)行測(cè)試。

二、Robotium自動(dòng)化測(cè)試的原理

Robotium是基于instrumentation的二次封裝。Roboiutm分查找控件和點(diǎn)擊控件兩大類操作。查找控件的原理是:在waitter的waitForView()方法里面通過java反射獲得視圖,并匹配所需要的控件,查找并返回控件對(duì)象。點(diǎn)擊控件的原理是:查找到的控件對(duì)象解析包裝成MotionEvent,基于Instrumentation框架,通過InputManager注入事件。調(diào)用類組織結(jié)構(gòu)如下圖簡(jiǎn)示:


Robotium自動(dòng)化原理簡(jiǎn)圖

三、第一個(gè)Robotium自動(dòng)化工程

話不多說,開始Robotium自動(dòng)化測(cè)試工程吧!

環(huán)境準(zhǔn)備:
操作系統(tǒng):windows
android SDK
IDE:eclipse+ADT插件
不需源碼,只要一個(gè)apk作為被測(cè)對(duì)象。(需要打包apk時(shí)生成的R文件)這里我們用網(wǎng)易云閱讀的apk作為被測(cè)對(duì)象。

3.1 apk重命名&安裝被測(cè)應(yīng)用

Robotium框架需要被測(cè)應(yīng)用和測(cè)試工程需要使用相同的簽名,這樣才可以使用Instrumentation把被測(cè)應(yīng)用啟動(dòng)起來。我們本機(jī)eclipse使用的簽名文件可以從window-> Preferences->Android->Build中查看,一般情況下一般存放于C:\Users\yourUserName.android目錄下。如下圖所示:


從圖中看來我的Eclipse工程使用的是C盤下的debug.keystore文件,那么需要將被測(cè)apk用此keystore文件重簽名然后裝到真機(jī)或者測(cè)試機(jī)上就OK了。
重簽名可使用重簽名工具re-sign.jar

3.2 新建Robotium自動(dòng)化測(cè)試工程

1.新建工程
在Eclipse上點(diǎn)擊File->New->Other->Android->Android Test Project,命名后點(diǎn)擊Next,Test Target選擇“This Project”,然后點(diǎn)Next直至Finish為止。注:可能有時(shí)候會(huì)出現(xiàn)Eclipse報(bào)Null Pointer Exception錯(cuò)誤,解決方案可參考。

2.添加Robotium Jar包
右鍵該項(xiàng)目,選擇property然后選擇java build path, 選擇 Add External JARs,選擇下到的robotium-solo-5.1.jar。(注:Robotium可從網(wǎng)上下載Jar包)

3.新建測(cè)試用例
在項(xiàng)目下新建一個(gè)package,在package下新建一個(gè)測(cè)試類,該類繼承自ActivityInstrumentationTestCase2。如下圖簡(jiǎn)示:



注意到這里我新建了另一個(gè)package,里面只放了R.java文件,不能與測(cè)試文件放在同一個(gè)package下(會(huì)報(bào)錯(cuò))。而com.pris.test這個(gè)package下新建了一個(gè)測(cè)試類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打開應(yīng)用程序主界面
        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("沒有調(diào)起應(yīng)用", isOk);
        solo.sleep(3000);
        //進(jìn)入左欄賬號(hào)頁面
        boolean isFindAccountButton = solo.waitForView(R.id.account_btn, 1, 2000);
        Assert.assertTrue("沒有找到賬號(hào)控件", isFindAccountButton);
        View account_button = solo.getView(R.id.account_btn);
        solo.clickOnView(account_button);
       //點(diǎn)擊登陸按鈕,打開登陸頁面
        boolean isLoginButton = solo.waitForView(R.id.button_login, 1, 2000);
        Assert.assertTrue("沒有找到登陸控件", isLoginButton);
    }

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

代碼結(jié)構(gòu)較簡(jiǎn)單,包括一些靜態(tài)資源,一個(gè)構(gòu)造函數(shù),一個(gè)solo初始化方法,一個(gè)核心的測(cè)試方法,最后一個(gè)銷毀solo對(duì)象的結(jié)束方法。這里需要強(qiáng)調(diào)的是solo初始化setUp方法。有兩套初始化方法,分別適用于主界面是否就是MainActivity的情況。這里我用的網(wǎng)易云閱讀的apk進(jìn)行測(cè)試,它的MainActivity是SplashActivity(是一個(gè)廣告頁),沒有廣告或者廣告播放結(jié)束后進(jìn)入主界面,所以直接寫solo = new Solo(instrumentation,activity)的話是無法正確創(chuàng)建solo對(duì)象的。需要用Intent去打開應(yīng)用程序主界面。然后solo對(duì)象的話使用solo = new(instrumentation)構(gòu)造方法創(chuàng)建。

4.修改Manifest.xml文件
主要修改的地方是instrumentation中指定TargetPackage為待測(cè)試的包名,此外檢查manifest中的package是否就是本測(cè)試工程的包名。

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

    <instrumentation
        android:name="android.test.InstrumentationTestRunner"
        android:targetPackage="com.netease.pris" />   //這里是被測(cè)應(yīng)用程序的包名

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

5.執(zhí)行測(cè)試用例
在測(cè)試用例文件上右擊,選擇run as Android Junit Test,就可以進(jìn)行測(cè)試了。運(yùn)行結(jié)束,在Eclipse左右會(huì)顯示運(yùn)行結(jié)果。如果出錯(cuò),可以去查看logcat,排查錯(cuò)誤的原因。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容