巴黎的灯光下 发表于 2017-6-29 14:22:58

appium 自动遍历的参考代码

背景上次支付宝沙龙分享了基于appium的自动遍历小工具,有些朋友感兴趣, 想看下代码,
为了给大家一个参考, 我这里贴部分的关键算法代码给大家吧
这份代码写的很挫, 功能也很简单, 只是个演示demo, 是为了证明appium can do IT.
我计划用Java重构, 这个只当是参考吧
部分代码参考def capabilities
    {
      'browserName' => '',
      'device' => 'android',
      'version' => '4.1',
      'app-activity'=> 'com.taobao.tao.Welcome',
      'app-package'=> 'com.taobao.taobao'
      #'app-activity'=> '.activity.MainActivity',
      #'app-package'=> 'com.sankuai.meituan'
    }
end

def setup
    server_url = 'http://127.0.0.1:4723/wd/hub'
    @driver = Selenium::WebDriver.for(:remote, :desired_capabilities => capabilities, :url => server_url)
    @driver.manage.timeouts.implicit_wait = 30 # seconds
    puts 'sleep 20'
    sleep 20
    @driver
end
def config()
    @config={}
    @config['blacklist']=['立即抢购', '美团承诺 团购无忧', '退款']
end

def refresh()
    root=[]
    el_array=@driver.find_elements(:xpath, "//text[@clickable=true]")
    #如果点击没有发生变化, 就跳过
    if el_array.size==@list.size
      return @list
    end
    el_array.each do |node|
      begin
            text=node.text
            location=node.location
            is_skip=false
            next if text.strip==''
            next if text.size<2
            @config['blacklist'].each do |keyword|
                if text.index(keyword)
                  is_skip=true
                  break
                end
            end
            next if is_skip
            current={}
            current['click']=false
            #位置相差不大 也认为是相同
            current['sign']=text+'|'+location.x.to_s
            current['text']=text
            current['object']=node
            root << current
      rescue Exception=>e
            puts e.message
      end
    end
    root
end
def find_return_root(el)
    current=nil
    @nodes.each do |node|
      if node.content['sign']==el['sign']
            current=node
            break
      end
    end
    current=current.parent if current
    return(current)
end
def travel()
    @list||=[]
    @nodes ||= Tree::TreeNode.new("ROOT", {})
    @current||=@nodes
    @index||=0
    @index+=1
    @list=refresh()
    has_new=false
    return_root=nil
    @list.each do |el|
      #判断是否曾经出现过
      return_root=find_return_root(el)
      if return_root==nil
            has_new=true
            #如果是新元素, 就添加到tree中
            @current << Tree::TreeNode.new(el['sign'], el)
      end
    end
    #如果没有新元素, 代表回到某个父节点
    if has_new==false
      @current=return_root
    end
    save()
    if @current.level>7
      @driver.navigate.back
      travel()
    end

    #从未被点击的地方点击
    current=nil
    @current.children.each do |child|
      if child.content['click']==false
            current=child   
            @list.each do |node|
                if node['sign']==current.content['sign']
                  current.content['click']=true
                  @current=current
                  node['object'].click
                  sleep 3
                  travel()
                  break
                end
            end
            break               
      end
    end
    if current==nil
      @driver.navigate.back
      travel()
    end
end
运行结果因为这次采用的是uiautomator, 代码也优化, 所以执行时间很长
跑十几分钟, 手机就因为锁屏失败, 所以针对淘宝app, 我一直没跑全过, 生成的思维导图只是淘宝部分栏目的浅层结构图 想跑全的话, 就自己修改手机, 或者用虚拟机吧
如下是生成的结果:

https://testerhome.com/photo/2014/5eb803b3a9225862928e68d348177ef5.png
计划我接下来, 我在做上次分享的ppt最后一页的事情, 我想基于这个搞个在线服务. 有实力感兴趣的同学可以报名参加.
主要是为第三方的企业提供app遍历和附加服务. 一个实验性的技术项目.
目标

[*]优化速度
[*]优化算法, 解决回环
[*]自动生成appium的自动化代码
[*]支持规则
[*]从ruby转到java上去实现
[*]做个服务网站
[*]支持dom diff和灰度对比

巴黎的灯光下 发表于 2017-6-29 14:46:11

重要的是算法,点击这个没什么, 点击是入口, 现在只是纯点击, 以后加了规则, 就可以支持更多操作了, 比如滑动, 自动输入. 目前还得加上回环算法才算靠谱 所以除了怕嘲笑, 我也觉得没什么可保留的 , 就贴出来给大家参考下.

大家有好的思路, 也不放show下, 欢迎指教
另外, 这种纯黑盒的方式也不太好, 通过插桩可以获得更多的建模数据. 也是个缺点, 还需要继续想办法. 我倒是挺喜欢百度Cafe的做法.使用hook来解决
页: [1]
查看完整版本: appium 自动遍历的参考代码