mthoutai

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

简单介绍

项目一直是手工測试为主,加上一直是TV类应用。非常多自己主动化工具都没有针对TV类项目做非常好的适配,所以仅仅有自己动手了。

主要针对项目的特殊性进行了部分改造,不一定适用于其它项目。(涉及隐私,就不提供json文件和软件名字啦)

痛点

1.非标准控件的难处
这里写图片描写叙述
通过uiautomatorviewer获取到的不一样的磁贴,属性所有同样(除了坐标点),意味着没法通过id和class+index方式获取。text属性为空,也就没有办法通过byText的方式获取uiobject,高度定制的磁贴,让自己主动化非常为难,假设通过坐标点。太坑爹,不能跨设备,还是坑。

2.TV类应用没有触摸操作
TV类安卓程序,主要面向的是遥控器。也就是接收的是keyevent。所以touch事件显得不这么全面,为了最接近用户。还是选择用key来做自己主动化。

架构模块

这里写图片描写叙述

解析模块

从server解析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<CellInfo> startParse(String url) {
        String str = IOUtils.readFromNet(url);
        if(str==null){
            return null;
        }
        JSONObject jsonObject = new JSONObject(str);
        List<CellInfo> list = new ArrayList<CellInfo>();
        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<CellInfo> 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做集成还是非常easy的。仅仅要把jar包放在一个固定的文件夹,然后shell命令运行就完事了。
这里写图片描写叙述
然后定时任务自己选吧,构建失败的邮件提醒这里设置的是,上面我自己定义的异常类,当控制台输出我的异常类,那么会觉得不通过,然后触发邮件提醒。
这里写图片描写叙述
那么至此。一个较为完整的流程就完毕啦,那么在此框架上组员们(就我一个)就能够更进一部去完好二级页面的自己主动化用例了。

版权声明:本文为博主原创文章。转载请说明出处!

举报

  • 本文已收录于下面专栏:

相关文章推荐

android自己主动化測试-UiAutomator经常使用类

前面总结了uiautomator的用法: android自己主动化測试-UiAutomator使用入门 这里对我们写脚本时经常使用的一些类进行总结:  UiDevice类: 1.takeScree...

android自己主动化測试框架(一) uiautomator

Android自己主动化測试主要分为Monkeyrunner、Rubotium、UiAutomator、Monkey等。主要特点:<br style="font-size: 14px; font-family: Arial; color: #333333; line-height: 2

谷歌原生自己主动化框架UiAutomator1.0

5小时搞定谷歌原生自己主动化框架UiAutomator1.0 原文  http://tmq.qq.com/2016/06/androidautotestframwork-uiautomator/ ...

android自己主动化測试框架(一) uiautomator(2)

waitForWindowUpdate(final String packageName, long timeout) 等待符合packageName的应用触发 <

【腾讯TMQ】5小时搞定谷歌原生自己主动化框架UiAutomator1.0

谷歌对UI測试(UI Tetsting)的概念是:确保用户在一系列操作过程中(比如键盘输入、点击菜单、弹出对话框、图像显示以及其它UI控件的改变)。你的应用程序做出正确的UI响应。

基于android的web app 自己主动化測试

乔布斯有一次谈到这个问题,他说Web是未来。尽管现阶段Native给了用户更好的体验。

假设现

UiAutomator自己主动化測试框架的使用

简单介绍UiAutomator 是 Google 在 Android4.1 推出的一套黑盒 UI 自己主动化測试框架。用于做 UI 自己主动化的框架,主要模拟人来操作手机,如点击、长按、滑动、按键、文本输入等操作...

Android UiAutomator 自己主动化測试

一、一个BUG引发的问题 假设研发过程中有一个BUG:“不断的切换手机语言出现花屏现象”。这个问题我们怎样验证呢?我想,最好的方式应该是自己主动化測试。 那么,自己主动化測试能够完毕哪些任务呢? 简单的说,那些反复性的測试工作,都能够交给自己主动化完毕: 1、设置手机的语言 2、加入、删除、收藏联系人 3、拨号、挂断 4、甚至发送短信、收藏短信 假设须要上面的功能。那么就開始自己主动化之旅吧。

二、Android自己主动化測试简介 Android自己主动化測试主要分为Mo

5小时搞定谷歌原生自己主动化框架UiAutomator1.0

转载地址:http://tmq.qq.com/2016/06/androidautotestframwork-uiautomator/ 谷歌对UI測试(UI Tetsting)的概念是:...
  • 微博
    微信
    QQ
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多仅仅同意输入30个字)

posted on 2017-08-13 17:17  mthoutai  阅读(337)  评论(0编辑  收藏  举报