码迷,mamicode.com
首页 > 其他好文 > 详细

Robotium整体源码浅析

时间:2016-05-12 19:15:37      阅读:214      评论:0      收藏:0      [点我收藏+]

标签:

只能是浅析,不敢说什么解析,对比网上大神的详细分析,只能从整体去分析相关的东西,什么时候才能深入算法层面呢?

概述

在分析源码之前,我们先来看看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方法点击屏幕

Robotium整体源码浅析

标签:

原文地址:http://blog.csdn.net/cloud_huan/article/details/51354833

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!