Robotium整体源码浅析

来源:互联网 发布:mac日记本软件 编辑:程序博客网 时间:2024/05/01 03:51

概述

在分析源码之前,我们先来看看robotium给我们提供了什么样的类。
这里写图片描述

入口

在对整体有了一个认知之后,我们从solo类入口,因为solo是robotium的入口类,也是最重要的类,先来看看构造方法:

private Solo(Config config, Instrumentation instrumentation, Activity activity) {        if(config.commandLogging){            Log.d(config.commandLoggingTag, "Solo("+config+", "+instrumentation+", "+activity+")");        }        this.config = (config == null) ? new Config(): config;        this.instrumentation = instrumentation;        this.sleeper = new Sleeper();        this.sender = new Sender(instrumentation, sleeper);        this.activityUtils = new ActivityUtils(config, instrumentation, activity, sleeper);        this.viewFetcher = new ViewFetcher(instrumentation, sleeper);        this.screenshotTaker = new ScreenshotTaker(config, instrumentation, activityUtils, viewFetcher, sleeper);        this.dialogUtils = new DialogUtils(instrumentation, activityUtils, viewFetcher, sleeper);        this.webUtils = new WebUtils(config, instrumentation,viewFetcher, sleeper);        this.scroller = new Scroller(config, instrumentation, viewFetcher, sleeper);        this.searcher = new Searcher(viewFetcher, webUtils, scroller, sleeper);        this.waiter = new Waiter(instrumentation, activityUtils, viewFetcher, searcher,scroller, sleeper);        this.getter = new Getter(instrumentation, activityUtils, waiter);        this.clicker = new Clicker(activityUtils, viewFetcher,sender, instrumentation, sleeper, waiter, webUtils, dialogUtils);        this.setter = new Setter(activityUtils, getter, clicker, waiter);        this.asserter = new Asserter(activityUtils, waiter);        this.checker = new Checker(viewFetcher, waiter);        this.zoomer = new Zoomer(instrumentation);        this.swiper = new Swiper(instrumentation);        this.tapper =  new Tapper(instrumentation);        this.illustrator = new Illustrator(instrumentation);        this.rotator = new Rotator(instrumentation);        this.presser = new Presser(viewFetcher, clicker, instrumentation, sleeper, waiter, dialogUtils);        this.textEnterer = new TextEnterer(instrumentation, clicker, dialogUtils);        this.systemUtils = new SystemUtils(instrumentation);        initialize();    }

排除了重载的构造方法,可以看到初始化solo对象的时候会传入三个参数, Config对象
Instrumentation对象,activity对象。后两个就不多说了,在学习instrumentation框架的时候已经知道了instrumentation对象是在运行之前注入到被测应用中去的,而activity重要性也不多说啦,于是就剩下Config,这个对象是运行robotium的一些设置参数,我们看看有什么:

    public static class Config {        /**         * The timeout length of the get, is, set, assert, enter and click methods. Default length is 10 000 milliseconds.         */        public int timeout_small = 10000;        /**         * The timeout length of the waitFor methods. Default length is 20 000 milliseconds.         */        public int timeout_large = 20000;        /**         * The screenshot save path. Default save path is /sdcard/Robotium-Screenshots/.         */        public String screenshotSavePath = Environment.getExternalStorageDirectory() + "/Robotium-Screenshots/";        /**         * The screenshot file type, JPEG or PNG. Use ScreenshotFileType.JPEG or ScreenshotFileType.PNG. Default file type is JPEG.         */        public ScreenshotFileType screenshotFileType = ScreenshotFileType.JPEG;        /**         * Set to true if the get, is, set, enter, type and click methods should scroll. Default value is true.         */        public boolean shouldScroll = true;        /**         * Set to true if JavaScript should be used to click WebElements. Default value is false.         */        public boolean useJavaScriptToClickWebElements = false;        /**         * The screenshot file type, JPEG or PNG.         *         * @author Renas Reda, renas.reda@robotium.com         *         */        public enum ScreenshotFileType {            JPEG, PNG        }        /**         *  Set to true if Activity tracking should be enabled. Default value is true.         */        public boolean trackActivities = true;        /**         * Set the web frame to be used by Robotium. Default value is document.           */        public String webFrame = "document";        /**         *  Set to true if logging should be enabled. Default value is false.         */        public boolean commandLogging = false;        /**         * The command logging tag. Default value is "Robotium".         */        public String commandLoggingTag = "Robotium";    }

之后就是一些类的实例化,initialize()方法则是超时时间初始化。

完成初始化的分析之后继续研究solo这个类,通读接口之后人为分成下面几个类别:

  1. 列表内容
  2. 构造初始化
  3. 断言
  4. 清除
  5. 点击–都会调用clickOn方法
  6. 拖拽
  7. 注入文本(typeText/enterText)
  8. 关闭
  9. Get类–getView
  10. 回退
  11. Check类
  12. Press按压类
  13. 滚动scroll类
  14. 搜索类
  15. set类
  16. 截图类
  17. 等待类

Robotium源码类浅析

webview相关就没有看了,因为没有用到

Asserter:
Robotium给我们新增的两个assert方法,当然都是在Asserter类定义的:
assertCurrentActivity和assertMemoryNotLow
assertCurrentActivity:检查当前的activity是否是我期望的activity,本质上是取出当前activity的实例然后getclassName,最后通过Assert.assertEquals方法判断的

Activity activity = activityUtils.getCurrentActivity();            if(activity != null){Assert.assertEquals(message, name, activity.getClass().getSimpleName());

assertMemoryNotLow:检查当前系统是否内存不足,充足那么通过,原理是通过
ActivityManager.MemoryInfo对象来检查

ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo();((ActivityManager)activityUtils.getCurrentActivity().getSystemService("activity")).getMemoryInfo(mi);

Checker:
这个类是用来判断某个view的状态的,我们举例其中一个方法:
这里写图片描述
这是判断按钮可不可以点击,waiter方法是筛选条件作用,并转化为view,最后调用的其实是widget自身的属性状态
这里写图片描述
再举例其他的方法
这里写图片描述

Clicker:
点击方法一直是自动化的重点对象,直接看clickOnScreen
这里写图片描述
因为根据原理,查找到期望的view之后,最终都会转为xy坐标,并调用上面这个方法去点击屏幕。而clickOnScreen的本质还是调用了instrumentation的sendPointSync方法,实现注入点事件。
当然还是有两个不是调用点击屏幕的方法
clickLongOnTextAndPress
clickOnActionBarItem/clickOnActionBarHomeButton

Scroller:
滚动的类,包括两个操作drag和一些可以滚动的操作
Drag执行的操作是DOWN–>MOVE–>UP,调用的还是sendPointSync方法
这里写图片描述
至于列表的滚动操作,通过runOnMainSync的堵塞方法,在主线程直接调用view的
setSelection方法直接滚到第N行的。
这里写图片描述

Searcher:
负责查找和定位控件的类,这个类主要是根据文字获取文字控件的,然后返回一个view,主要看searchFor这个方法。
这里写图片描述
那么这个方法的原理是通过viewFetcher.getCurrentViews(viewClass, true)方法获取所有控件,然后遍历所有控件,通过正则匹配控件,当匹配到则返回view,也就是上面的返回值了,再者,有一点要注意,查找会提供自动滚滚动的操作,只需要传入参数设置为true即可,比较方便。
这里写图片描述

TextEnterer:
Robotium支持两种文本注入,api也已经告诉了我们
这里写图片描述
前者就是我们单元测试经常用的setText方法,后者则是调用了instrumentation的sendStringSync方法注入,而sendStringSync会把string分成一个一个字符,然后循环一个个调用sendKeySync方法,所以调用第二种方法注入你可以看到输入轨迹
这里写图片描述

ViewFetcher:
这里面封装了所有查找view的方法。
这里写图片描述
这里写图片描述
那么通过上面可以知道是通过windowManager的相关方法取得里面的DecorViews,也就是控件树,剩下的方法都是如何去筛选DecorViews里面相关的内容,就不多说啦。

总结:
那么一路下来呢,可以发现这么个规律
1.查找控件都是通过取得window下的DecorViews然后迭代对比得到的
2.查找控件之后view都会转换为xy坐标,最终调用instru的sendPointSync方法点击屏幕

0 0
原创粉丝点击