Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android TV磁貼類app自動化框架二次改造(基於UiAutomator)

Android TV磁貼類app自動化框架二次改造(基於UiAutomator)

編輯:關於Android編程

簡介

項目一直是手工測試為主,加上一直是TV類應用,很多自動化工具都沒有針對TV類項目做很好的適配,所以只有自己動手了。主要針對項目的特殊性進行了部分改造,不一定適用於其他項目。(涉及隱私,就不提供json文件和軟件名字啦)

痛點

1.非標准控件的難處
這裡寫圖片描述
通過uiautomatZ喎?/kf/ware/vc/" target="_blank" class="keylink">vcnZpZXdlcrvxyKG1vbXEsrvSu9H5tcS0xcz5o6zK9NDUyKuyv8/gzawos/3By9f4seq14ymjrNLizrbXxcO7t6jNqLn9aWS6zWNsYXNzK2luZGV4t73KvbvxyKGjrHRleHTK9NDUzqq/1aOs0rK+zcO709Cw7Leozai5/WJ5VGV4dLXEt73KvbvxyKF1aW9iamVjdKOsuN+2yLao1sa1xLTFzPmjrMjD19S2r7uvutzOqsTRo6zI57n7zai5/df4seq146OszKu/07X5o6yyu8Tcv+fJ6LG4o6y7ucrHv9OhozwvcD4NCjxwPjxzdHJvbmc+Mi5UVsDg06bTw8O709C0pcP+stnX9zwvc3Ryb25nPjxiciAvPg0KVFbA4LCy17+zzNDyo6zW99Kqw+bP8rXEysfSo7/YxvejrNKyvs3Kx73TytW1xMrHa2V5ZXZlbnSjrMv50tR0b3VjaMrCvP7P1LXDsrvV4sO0yKvD5qOszqrBy9fuvdO9/NPDu6ejrLu5ysfRodTx08NrZXnAtNf219S2r7uvoaM8L3A+DQo8aDIgaWQ9"架構模塊">架構模塊

這裡寫圖片描述

解析模塊

從服務器解析json文件格式,包裝成實體類CellInfo,返回一個包含磁鐵信息的List。一個磁鐵對應一個CellInfo,一個CellInfo需要提取的信息有

x坐標 y坐標 所屬的Tab分類頁 每個磁鐵的說明標簽

所以對應的定義如下:

package launcherClick.model;

public class CellInfo {

    private String label;
    private String tab;

    public String getTab() {
        return tab;
    }

    public void setTab(String tab) {
        this.tab = tab;
    }

    private int x;
    private int y;

    public String getLabel() {
        return label;
    }

    public void setLabel(String label) {
        this.label = label;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

}

解析用的是第三方開源庫org.json,對應的解析代碼如下:

package launcherClick;

import java.util.ArrayList;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONObject;

import Utils.IOUtils;
import Utils.Println;
import launcherClick.model.CellInfo;

public class AMetroParse {

    public static List startParse(String url) {
        String str = IOUtils.readFromNet(url);
        if(str==null){
            return null;
        }
        JSONObject jsonObject = new JSONObject(str);
        List list = new ArrayList();
        JSONArray _tabs = jsonObject.getJSONArray("tabs");
        for(int i = 0;i<_tabs.length();i++){
            String tab = _tabs.getJSONObject(i).getString("label");
            JSONArray _cells = _tabs.getJSONObject(i).getJSONArray("cells");
            for(int j=0;j<_cells.length();j++){
                CellInfo cellInfo = new CellInfo();
                cellInfo.setX(_cells.getJSONObject(j).getJSONObject("location").getInt("x"));
                cellInfo.setY(_cells.getJSONObject(j).getJSONObject("location").getInt("y"));
                cellInfo.setLabel(_cells.getJSONObject(j).getJSONObject("content").getString("label"));
                cellInfo.setTab(tab);
                list.add(cellInfo);
            }
        }
        return list;
    }
}

坐標轉換模塊

這部分的工作是把上一步驟解析後的實體類進行提取和處理,主要處理的內容是根據x y坐標計算磁鐵移動量,更具x的極大值和分類頁做跨分類移動的偏移計算以及一些其他處理。
通過x y計算偏移比較簡單,只是簡單計算距離:

        for (CellInfo cellInfo : list) {
            if (cellInfo.getLabel().contains(label)
                    && cellInfo.getTab().contains(tab)) {
                int x = cellInfo.getX();
                int y = cellInfo.getY();
                new Println("x:" + x + "  " + "y:" + y + "  " + "偏移量" + _offset);
                // x方向
                for (int i = x + _offset; i > 1; i--) {
                    new Println("→" + " count is " + (x + _offset));
                    keyRight();

                }
                // y方向
                for (int i = y; i > 1; i--) {
                    new Println("↓");
                    keyDown();
                }
            }
        }

恩,裡面有個偏移量,跨分類用的,偏移量是通過每個分類下磁鐵最大值得出來的,每一個分類最後一個磁鐵的x值即為最大值,遍歷當前分類下的所有磁鐵的x,如果大於後面一個,則放在前面,下次再用這個值去比較下面的x值。忘記這是什麼排序算法了…囧…當然,也可以用Collections的自帶的算法。

    private int togicOffset(String tab) {
        int lineLenth = 0;
        List list = AMetroParse
                .startParse("我是隱藏的接口");
        for (CellInfo cellInfo : list) {
            if (cellInfo.getTab().contains(tab)) {
                int x = cellInfo.getX();
                lineLenth = lineLenth >= x ? lineLenth : x;
            }
        }
        return lineLenth;
    }

那麼通過上面的排序之後,就可以得到每個分類的偏移量,這樣對於後面的分類磁貼,就可以知道磁貼在整體的真正位置啦,於是就可以開始移動了。

        for (CellInfo cellInfo : list) {
            if (cellInfo.getLabel().contains(label) && cellInfo.getTab().contains(tab)) {
                int x = cellInfo.getX();
                int y = cellInfo.getY();
                new Println("x:" + x + "  " + "y:" + y + "  " + "偏移量" + _offset);
                // x方向
                for (int i = x + _offset; i > 1; i--) {
                    new Println("→" + " count is " + (x + _offset));
                    keyRight();

                }
                // y方向
                for (int i = y; i > 1; i--) {
                    new Println("↓");
                    keyDown();
                }
            }
        }

圖片比較模塊

來源於monkeyrunner的思路,原理是計算兩個bitmap的長寬,然後提取出裡面每個像素的像素值,如果相同,相似度+1,最後再除以總像素值(比如1280x720),這樣就可以把相似程度轉為一個一個可以衡量的具體值了,那麼判斷這個界面是不是我需要點擊的時候,只需要截屏當前圖片和預期的圖片對比,相似度達到100的時候就認為是正確的。當然也提供了局部比較的功能,比如獲取不到數據的異常提示。那麼代碼如下,提供了多種重載的方法以及兩個assert判斷。

package Utils;

import junit.framework.Assert;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

public class ImageCompare {

    public  static void AssertBitmapEqual(Bitmap bitmap0, Bitmap bitmap1){
        /**
         * 百分百圖片相同斷言-.-
         */
        Assert.assertEquals(100, ImageCompare(bitmap0,bitmap1));
    }

    public  static void AssertBitmapNotEqual(Bitmap bitmap0, Bitmap bitmap1){
        /**
         * 百分之零圖片相同斷言
         */
        Assert.assertEquals(0, ImageCompare(bitmap0,bitmap1));
    }

    public static int ImageCompare(String path0,String path1) {
        /**
         * 提供根據路徑直接比較
         */
        Bitmap bitmap0 = BitmapFactory.decodeFile(path0); 
        Bitmap bitmap1 = BitmapFactory.decodeFile(path1); 
        return ImageCompare(bitmap0,bitmap1);
    }

    public static int ImageCompareChild(Bitmap bitmap0, Bitmap bitmap1,int x,int y,int width,int height) {
        /**
         * 裁剪子圖並比較,主要是為了解決拉取動態數據不同,但是局部提示不變的比較場景。
         */
        Bitmap bitmap00 = bitmap0.createBitmap(bitmap0, x, y, width, height);
        Bitmap bitmap01 = bitmap1.createBitmap(bitmap1, x, y, width, height);
        return ImageCompare(bitmap00,bitmap01);
    }

    public static int ImageCompare(Bitmap bitmap0, Bitmap bitmap1) {
        /**
         * 比較的主函數
         * 只能比較相同長寬的圖片,不相等返回-1失敗
         * 相似度為1~100
         * 原理是提取每一個像素點比較,整張圖相似度取決於像素點相同個數,所以還是比較准確的
         */
        int picPct = 0;
        int picCount = 0;
        int picCountAll = 0;
        new Println("begin to compare");
        if (bitmap0 == null || bitmap1 == null) {
            new Println("null bitmap");
            return -1;
        }
        if (bitmap0.getWidth() != bitmap1.getWidth()
                || bitmap0.getHeight() != bitmap1.getHeight()) {
            return -1;
        }
        new Println("寬度為:" + bitmap1.getWidth() + "高度為:" + bitmap1.getHeight());
        for (int j = 0; j < bitmap1.getWidth(); j++) {
            for (int i = 0; i < bitmap0.getHeight(); i++) {
                if (bitmap0.getPixel(j, i) == bitmap1.getPixel(j, i)) {
                    picCount++;
                }
                picCountAll++;
            }
        }
        int result = (int) (((float) picCount) / picCountAll * 100);
        new Println(picCount + "/" + picCountAll);
        new Println("相似度為:" + result);
        return result;
    }
}

異常&&其他模塊

定義了一些異常類,主要功能用於提示,這個提示的作用後面會用到。
增加了啟動應用和關閉應用的方法,原理是用到了shell命令。

Runtime.getRuntime().exec("am start -n 我是包名隱藏者");

初始化方法,主要用於異常時能夠一鍵重新開始,以及磁貼復原功能,還有其他一些小的處理就不多說啦,下面開始持續構建。

自動化的持續集成

還是那句話,不持續集成的自動化不是自動化,所以這裡介紹的是基於jenkins的自動化集成,其實UiAutomator做集成還是很容易的,只要把jar包放在一個固定的目錄,然後shell命令執行就完事了。
這裡寫圖片描述
然後定時任務自己選吧,構建失敗的郵件提醒這裡設置的是,上面我自定義的異常類,當控制台輸出我的異常類,那麼會認為不通過,然後觸發郵件提醒。
這裡寫圖片描述
那麼至此,一個較為完整的流程就完成啦,那麼在此框架上組員們(就我一個)就可以更進一部去完善二級頁面的自動化用例了。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved