輔助程序實現黑盒自動化測試的常見問題

2021-02-13 360技術

輔助程序(Accessibility)在大多數機型上具有重啟設備後被激活的特性,可以完成Android測試框架(Uiautomator1.0、Uiautomator2.0)無法實現的功能。本文介紹如何搭建輔助程序和如何利用輔助程序進行黑盒測試。並總結了利用輔助程序執行黑盒測試遇到的問題,並在文末總結了各測試方案的應用場景。

輔助程序實現黑盒自動化測試的特點


輔助功能相較於測試框架在部分場景下有一定的優勢,可以做更多場景的測試:

1. 運行輔助程序過程中可以執行Uiautomator1.0或Uiautomator2.0測試用例,執行測試用例過程中輔助程序會被中斷,當測試用例執行結束後輔助程序會恢復運行;

2. 大部分機型重啟設備,服務會自動運行,可以測試部分app開機自啟功能等功能;

3. 由於是App方案,所以可以直接讀取手機簡訊,設備插上手機卡後,可以在邏輯數據層攔截簡訊驗證碼,實現程序的驗證碼登陸;

4.輔助程序有較高的優先級,程序保活能力非常強;


由於測試方式是基於Accessibility服務的app,所以也有很多限制:

1. 和被測應用不在同一進程內,相較於Uiautomator2.0隻能做黑盒測試;

2. 由於是App實現方案,所以在各系統上存在權限問題,不能像Uiautomator1.0一樣獲取系統運行信息(最近運行的應用、當前顯示的activity)

3. 執行點擊動作需要使用AccessibilityNodeInfo#performAction方法,但是此方法只能在clickable=true時生效;

4. 無法直接操作屏幕,需要藉助AccessibilityService的手勢功能實現滑動屏幕、點擊屏幕等動作;

5. 由於系統限制,高版本系統中啟動其他App失敗;

6. 發送鍵盤事件受限制,只能發送Home、back、打開通知、打開快捷設置、打開電源彈窗等有限功能;

7. 輔助程序異常退出時會關閉輔助程序配置,需要在設置頁面手動配置;

輔助程序服務配置與黑盒自動化測試實現

自定義AccessibilityService服務,在服務內重載系統方法,

初始化測試服務:重載onServiceConnected方法

當服務激活時調用此方法,在這裡進行服務的初始化工作,主要配置onAccessibilityEvent方法感知的事件類型和服務配置。

1、獲取AccessibilityServiceInfo 對象:

getServiceInfo()方法獲取當前使用的AccessibilityServiceInfo對象,如果方法返回null,直接通過AccessibilityServiceInfo()構造方法創建。

 AccessibilityServiceInfo accessibilityServiceInfo = getServiceInfo();
if (accessibilityServiceInfo == null) {
    accessibilityServiceInfo = new AccessibilityServiceInfo();
    setServiceInfo(accessibilityServiceInfo);
}

2、設置AccessibilityServiceInfo#eventTypes標記過濾AccessibilityEvent事件類型:

直接通過或運算符(|)添加標記,下面代碼配置過濾控制項點擊、控制項選擇、控制項獲取焦點和文本變化事件,發生配置的事件時會調用onAccessibilityEvent方法。

accessibilityServiceInfo.eventTypes |= AccessibilityEvent.TYPE_VIEW_CLICKED;
accessibilityServiceInfo.eventTypes |= AccessibilityEvent.TYPE_VIEW_SELECTED;
accessibilityServiceInfo.eventTypes |= AccessibilityEvent.TYPE_VIEW_FOCUSED;
accessibilityServiceInfo.eventTypes |= AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED;

3、 設置AccessibilityServiceInfo#flags配置測試能力:

下面的代碼在默認配置基礎上增加WebView測試能力。

accessibilityServiceInfo.flags |= AccessibilityServiceInfo.DEFAULT;
accessibilityServiceInfo.flags |= AccessibilityServiceInfo.FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY;

AccessibilityServiceInfo.FLAG_REQUEST_FILTER_KEY_EVENTS標記慎用,如果增加此標記,輔助程序會攔截設備按鍵事件,會導致點擊返回鍵、home鍵無效。

4、更新配置信息:
需要調用
AccessibilityServiceInfo#setServiceInfo(AccessibilityServiceInfo info)
方法更新配置。

重載
onAccessibilityEvent(AccessibilityEvent accessibilityEvent)
方法,感知頁面變化。

當發生頁面變化時回調此方法,可用於觸發自動處理彈窗的業務

重載onInterrupt()方法,釋放資源

當系統中斷輔助服務時調用(例如執行自動化測試用例),可以在這個方法內釋放資源。

配置測試服務

配置清單文件:

需通過meta-data標籤指定accessibilityservice配置文件,該文件位於res/xml文件夾下。

<service
    android:label="輔助按鍵服務"
    android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
    android:exported="true"
    android:directBootAware="true"
    android:name=".service.TaskAccessibilityService">
    <intent-filter>
        <action android:name="android.accessibilityservice.AccessibilityService"/>
    </intent-filter>
    <meta-data
        android:name="android.accessibilityservice"
        android:resource="@xml/accessibility_service_config" />
</service>

accessibilityservice配置輔助程序屬性:

android:description 配置輔助程序描述信息,在設置頁面中顯示

android:accessibilityFeedbackType 反饋方式

android:canPerformGestures 模擬手勢配置,輔助程序滑動屏幕時必須配置此屬性為true

android:accessibilityFlags
等同AccessibilityServiceInfo#flags的設置,可以在代碼中動態配置

res/xml/accessibility_service_config.xml文件信息:

<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:description="@string/accessibility_service_description"

    android:accessibilityFeedbackType="feedbackAllMask"
    android:canRetrieveWindowContent="true"
    android:canPerformGestures="true"
    android:notificationTimeout="100"
    android:accessibilityFlags="flagDefault"
    />

下面是AccessibilityService可以直接調用的方法概述,通過下面這些方法可以獲取UI測試過程中必要的數據和執行測試動作。

performGlobalAction方法參數為AccessibilityNodeInfo的靜態常量:

dispatchGesture實現點擊、滑動滑動屏幕

系統SDK<24時無法點擊和滑動屏幕,需要通過AccessibilityNodeInfo的performAction(int action)方法實現UI操作,參數指定ACTION_ACCESSIBILITY_FOCUS獲取焦點、ACTION_LONG_CLICK執行長點擊、執行ACTION_CLICK點擊。

屏幕滑動和點擊方法是藉助dispatchGesture方法模擬手勢實現的,通過Path指定屏幕滑動路徑,調用dispatchGesture方法實現Path指定的滑動方式。具體實現代碼如下:

Path mPath = new Path();
mPath.moveTo(startX, startY);//滑動的起始點
mPath.lineTo(endX, endY);//滑動終點。不指定lineTo的坐標,只配置moveTo坐標時執行點擊動作,點擊位置為moveTo指定的坐標。
    dispatchGesture(new GestureDescription.Builder().addStroke(new GestureDescription.StrokeDescription
            (mPath, 50, 500)).build(), new GestureResultCallback() {
        @Override
        public void onCompleted(GestureDescription gestureDescription) {
            super.onCompleted(gestureDescription);
            System.out.println("模擬手勢成功");
        }

        @Override
        public void onCancelled(GestureDescription gestureDescription) {
            super.onCancelled(gestureDescription);
            System.out.println("模擬手勢失敗");
        }
    }, null);
} else {
    System.out.println("系統不支持" + Build.VERSION.SDK_INT);
}

高版本系統通過intent啟動APP失敗

Android高版本系統對後臺程序啟動應用做了嚴格限制,解決這個問題有下面兩種方案

1. 輔助程序實現懸浮窗功能,在整個測試流程中App屬於前臺應用,具有啟動其他App的權限。缺點:各版本系統適配麻煩,測試過程中會檢測到懸浮窗。

2. 通過UI操作啟動App,在桌面滑動尋找被測應用的Launcher圖標,然後通過點擊操作打開App。

AccessibilityNodeInfo執行performAction失敗

performAction方法執行失敗是因為對應的AccessibilityNodeInfo不具有對應的操作屬性,比如執行點擊操作時AccessibilityNodeInfo#isClickable()方法返回false,此時點擊操作就會失敗。有兩種解決方案:

1. 尋找響應事件的AccessibilityNodeInfo執行performAction操作

由於當前AccessibilityNodeInfo無法響應點擊事件,那麼尋找AccessibilityNodeInfo#isClickable()返回true的父控制項執行操作。

public boolean clickNode(AccessibilityNodeInfo nodeInfo){
    AccessibilityNodeInfo actionNode=null;
    while (true){
        actionNode=nodeInfo.getParent();
        //循環時防止空指針異常
        if(actionNode==null){
            return false;
        }
        if(actionNode.isClickable()){
            break;
        }
    }
    //可能存在所有父控制項均不可點擊情況
    if(actionNode==null){
        return false;
    }
    actionNode.performAction(AccessibilityNodeInfo.ACTION_CLICK);
    return false;
}

2. 如果SDK >= 24,則計算AccessibilityNodeInfo的屏幕坐標,然後點擊對應的屏幕坐標即可。

public boolean clickNode(AccessibilityNodeInfo nodeInfo){
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
        //獲取控制項的屏幕坐標
        Rect rect=new Rect();
        nodeInfo.getBoundsInScreen(rect);
        //點擊屏幕坐標
        clickScreen(rect.centerX(),rect.centerY());
        return true;
    }else {
        return false;
    }
}

public void clickScreen(int x, int y) {
    Path mPath = new Path();
    mPath.moveTo(x, y);//配置點擊坐標

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        dispatchGesture(new GestureDescription.Builder().addStroke(new GestureDescription.StrokeDescription
                (mPath, 50, 50)).build(), new GestureResultCallback() {
            @Override
            public void onCompleted(GestureDescription gestureDescription) {
                super.onCompleted(gestureDescription);
                System.out.println("點擊成功");
            }

            @Override
            public void onCancelled(GestureDescription gestureDescription) {
                super.onCancelled(gestureDescription);
                System.out.println("點擊失敗");
            }
        }, null);
    } else {
        System.out.println("系統不支持" + Build.VERSION.SDK_INT);
    }
}

以上就是通過App實現黑盒測試的簡單介紹,再具體的信息可以查閱Android源碼,下面介紹一下幾種測試方案的使用場景:

權限:Shell權限,可以反射系統API實現常用功能,可以繞過Android安全機制,讀取最近運行APP、正在運行進程、強殺其他應用;

保活:保活能力較強,不會被Android系統釋放,可以用nohup模式異步運行,即使拔掉數據線也不影響服務(諾基亞手機除外);

場景推薦: 適用多App通用測試腳本,便於對腳本做項目擴展;提供遠程手機服務接口。Android R(11)模擬器不支持,兼容Android R系統的腳本需要注意。

權限:與被測App運行在相同進程內部,與被測APP具有相同權限;

保活:保活能力差,被測App進程結束時,腳本即停止運行;

場景推薦:可以直接操作被測App的方法,可以用於白盒測試,對長期維護的重點項目可以用來進行單元測試和複雜業務測試。

權限:單獨的App,跨進程操作,需單獨申請app權限;

保活:由於是Android專用場景的服務,所以保活能力非常強,部分機型即使重啟後服務依然存在,且不影響UiAutomator測試用例的執行,用例執行結束後服務自動恢復;

場景推薦:殘障人士輔助APP;設備維護服務;自動初始化程序運行環境等

相關焦點

  • 京東JMAC,完美解決移動自動化測試的常見問題
    儘管有這麼多開源框架,但在實施移動端自動化測試時,仍然面臨著眾多問題,以下列出幾個常見問題:安裝執行環境繁瑣,純手動APP產品不可擴展無法進行手機兼容性測試每臺設備對應多套腳本,復用率低,可移植性差、可維護性差、執行歷史很難追溯自動化執行局限於開發人員本地測試結果展現不清晰,無法精準定位問題針對這些問題
  • 基於自動化用例的精準測試探索
    基於黑盒的測試使的項目測試在測試過程中存在以下幾個問題:(1)黑盒測試受主觀人為因素影響太大:黑盒測試完全依賴測試人員的個人能力,經驗和業務熟悉度,受主觀因素影響太大,不確定性太多,這是產生漏測的根本原因。(2)測試覆蓋面無客觀數據可衡量:測試對代碼覆蓋程度,質量高低,沒有客觀數據可衡量,完全靠人為主觀介定。
  • 報表自動化測試——黑盒測試篇
    ,但由於參數組合的數量太大,人工測試的用例只能算九牛一毛,依然有大部分漏測的場景可能發現問題,上線之後被用戶投訴。基於這個背景,引入自動化測試,旨在通過程序窮舉出各種查詢場景自動進行測試,並記錄各場景的測試結果。需求從背景中收集到以下需求:頁面上有很多查詢條件窮舉查詢條件的組合記錄各組合的測試結果分析先看看頁面長什麼樣子。
  • 黑盒測試的7種測試方法
    黑盒測試也稱功能測試,它是通過測試來檢測每個功能是否都能正常使用。在測試中,把程序看作一個不能打開的黑盒子,在完全不考慮程序內部結構和內部特性的情況下,在程序接口進行測試,它只檢查程序功能是否按照需求規格說明書的規定正常使用,程序是否能適當地接收輸入數據而產生正確的輸出信息。
  • ​序|自動化測試概述
    首先根據測試方法來劃分,可以分為:黑盒測試:最基礎的功能測試,不關心內部的代碼實現,而僅驗證輸入輸出的正確性。白盒測試:基於邏輯驅動或者基於代碼測試,打開代碼內部的實現,去研究原始碼中的接口或者具體實現的正確性。其次,根據測試目標來劃分,又可以分為:兼容性測試:對產品和軟硬體之間的兼容性進行測試,比如軟體在各種不同安卓機型上的兼容性。
  • 重溫黑盒、白盒與灰盒測試方法
    對於黑盒、白盒與灰盒測試方法的理解,幾年前我在某乎做過一個概念性的回答,當時提問者詢問:如何跟非技術人員解釋黑盒、白盒、灰盒測試的區別?我的回答原文如下:既然是對非技術人員解釋,就不能用專業術語。這樣說吧,有個打孔機,類似這樣。
  • 精準測試
    而測試的難點就體現在以下幾個方面:(1)系統級的測試用的基本都是黑盒測試方法,從根本上註定基於黑盒測試方法的各種方法都沒有直接面對計算機所真正理解的程序層面去解決軟體測試問題。同時黑盒測試永遠帶有一種猜測的基因,過程非常不穩定,並且難以控制。
  • 最基礎的軟體測試總結
    按測試手段來分類測試時對象可見度:黑盒測試、白盒測試根據狀態:靜態測試、動態測試測試執行的方式:手工測試、自動化測試黑盒測試在測試中把我們被測試的系統或者軟體看成一個不能打開的盒子,在完全不考慮程序內部結構和內部特性的情況下,通過相關暴露出來的接口來對程序進行測試,黑盒測試只檢查程序的功能是否按照我們需求規格說明的規定能夠正常的使用,程序是否能夠適當的接收數據並產生正確的輸出信息。
  • 6年測試老鳥經驗分享:21條自動化測試常見問題及解決思路!
    提起自動化測試,可謂仁者見人,智者見智,心中五味雜陳啊!你從任何一個招聘渠道來看最近兩年對測試崗位的要求,幾乎都要求會自動化測試。而不少人一直認為手工測試才是王道,工作中有的時候也用不到程序,幹嘛在面試的時候要求寫代碼呢?明明自己的測試能力不錯,做了多年的功能測試,為什麼面試的時候四處碰壁呢?很是想不明白,難道業界最近幾年有點兒盲目推崇自動化測試了嗎?
  • 談談網際網路軟體精準測試
    緣起軟體測試可以分為白盒測試和黑盒測試,由於網際網路追求測試研發的低配比,這樣便促使測試人員,沒有精力去做白盒測試,更多的是通過黑盒測試低成本的進行質量驗證。另外,隨著分布式、微服務等複雜的軟體架構的出現,系統黑盒測試的複雜性提升,質量風險越來越不可控。精準測試的誕生,核心動因是對於軟體質量的要求。
  • 軟體測試常見面試問題,收好不謝
    常見問題 軟體測試的目的是什麼? 軟體測試的一般流程是怎麼樣的? 常見的測試類型有哪些?分別說明一下? 測試用例設計常用的方法有哪些?詳細說明一下?
  • 我從功能測試進階到自動化測試工程師的經驗總結~|Atstudy
    所以花了很多時間在功能測試用例的設計上,隨著項目越做越多,用例設計也變得手到擒來。自己的內心也不滿足於只做功能測試,覺得自動化測試很厲害的樣子,就去學了代碼基礎。但是有一個問題,學了代碼基礎還是不會做自動化測試,因為那時候還傻傻分不清自動化到底有哪幾種。隨著學習的深入,知道軟體測試中常見的自動化主要分為2種:一種是UI自動化,一種是接口自動化。那麼先學哪個呢?
  • 軟體測試江湖的神兵利器
    但是無可否認的是,良好的理論素養無論是解決工作中遇到的問題,還是未來的職業發展,都幫助甚大。本文整理匯總了軟體測試行業中常見的一些測試理論,供大家參考。 1、軟體測試按照測試分類有:黑盒測試和白盒測試。
  • 程序丨精選!騰訊WeTest遊戲測試技術專家答疑專場
    騰訊互娛WeTest測試專家張得俊、孫大偉,針對大家提出的關於兼容測試、性能測試、安全測試、弱網絡測試、Crash測試等問題,進行了全方位解答。小編為大家整理了部分精彩問答,點擊閱讀原文,可以查看全部問答哦!Q:Unity手遊切換到手機後端以後,經常會出現莫名其妙的問題?如何更好的測試這些問題?
  • 使用Ansible&Tower實現一鍵自動化測試
    我們先看一下之前的壓力過程以及現在通過ansible和tower實現壓力過程的操作步驟及時間成本對比:之前壓力過程Ansible&tower實現壓力過程操作步驟:1、通過xshell登錄測試虛機;2、修改nginx配置連接線下resin環境;3、分別到nginx、resin代碼路徑下check nginx
  • AI吃雞遊戲,自動化測試
    第二個階段叫腳本化的自動化測試。腳本化意思就是要寫腳本來測軟體了,這應該是現在軟體測試工作最常見的做法。不過和軟體測試腳本和寫軟體一樣,如果每次都從頭開始,很快就會發現很多功能其實高度類似,大量時間都是在做重複性的工作。那怎麼辦呢?於是就有了第三個階段。第三個階段叫測試框架。
  • 軟體測試中:常見英文及含義
    本文梳理了軟體測試中,常見英文及含義,希望對大家有所幫助 。:Non-Execution-Based Testing或Static testing代碼走查:Walk through 代碼審查:Code Inspection 技術評審:Review 動態測試:Execution-Based Testing 白盒測試:White-Box Testing 黑盒測試:Black-Box Testing
  • 自動化測試面試題
    你比較熟悉那種自動化測試工具?2. 你在你以前工作中是如何使用自動化測試工具的?3. 介紹一下你在利用自動化測試工具的過程中遇到的一些問題4. 你是如何計劃自動化測試的?5. 自動化測試能提高測試效率嗎?6. 什麼是data-driven automoation(數據啟動自動化)?7. 測試自動化的主要特徵有哪些?8.
  • 成為優秀自動化測試工程師的7個步驟
    不要忽視手動測試 雖然我了解公司正在轉向無代碼自動化測試工具,達到專家級別並跟上行業自動化測試工程師的競爭,但最初要關注手動測試概念非常重要。首先,我想強調使用手動和自動測試的事實。有關何時使用手動測試以及何時使用自動化測試的文章可以幫助您了解它們之間的區別。一旦掌握了這些差異,您就會明白自動化測試肯定是手動測試的替代品,但僅限於某種程度。所以,你無法避免編碼。
  • Android APP自動化測試框架實戰
    1、為什麼需要使用框架實現自動化測試  作為測試工程師,可能在代碼能力上相比開發工程師要弱一點