python 调用 graphviz,应用于绘制app UI遍历工具中路径可视化

1 为什么想调用这个?

目的是想要为一个APP UI自动遍历加一个小的优化,将遍历可视化并记录下便利的路径。


2 怎么做?

首先想到的是画图,类似于流程图一样,从一个页面通过点击哪个按钮到达另一个页面

网上找了下有什么工具可以绘制图片的,然后就找到了graphviz

网上有很多教程的,写这个是为了给自己看看的,记录自己做的事


3 达成的效果如何?

效果图如下:


                                                                           循环图全景(没有循环完毕)


  • 方块 为页面信息:里面展示的事安卓Activity名
  • 椭圆 为按钮信息 :里面包括按钮文本内容 和 按钮点击坐标,这里有局限性,APP中有些按钮是没有文本的,单从坐标也是很难看出按钮位置
  • 本页面 ->按钮 的连线 表示的是按钮从属于页面。
  • 按钮 -> 本页面 的连线 表示 点击该按钮还在本页面,未进行页面跳转
  • 按钮 -> 另一个页面 的连线 表示 点击该按钮跳转到另一个页面
  • 每一次点击都会有一个表示顺序的数字在该指向线中标出

4 缺陷以及优化点

1)很明显的一点就是,不太美观,遍历一旦复杂就会图片就会臃肿,光看这些图片感觉看不出啥来,但是比起没有总好点

2)不好看的话,就用想办法好看点,就是用颜色来弥补,画面太杂,用颜色好区分,个人感觉



5 怎么实现这个图片绘制的呢?

很简单呀,网上查就好。

啊不,我写这个是为了方便自己的,省得以后要用到了还要从头查起


首先,我查到的是 : 

--使用DOT来绘图

思路:写绘制脚本 -> 利用dot,绘制成图

脚本形如:

digraph G {
    main -> parse -> execute;
    main -> init;
    main -> cleanup;
    execute -> make_string;
    execute -> printf;
    init -> make_string;
    main -> printf;
    execute -> compare;
}

效果图:

然后在.dot所在路进行执行:

dot -Tpng G.dot -o g.png

现在发现,其实还没有装graphviz呢,哈哈哈哈

我是Mac,所以来一句安装命令吧

sudo brew install graphviz

简单用法,知道下面几点基本上就够用了:

  1. 有向图(digraph)用a->b,无向图(graph)用a--b
  2. 节点、边通过中括号中的key=value来设置,比如main[shape=box];将main节点设置为矩形;
  3. 连接点的方向可以通过b->c:se;进行指定;
  4. 使用subgraph定义子流程图;
还有一些其他的用法:这里推荐一个链接:https://www.jianshu.com/p/5b02445eca1d
还蛮详细的。


但是,我是要把这个写到便利工具中的,一开始的想法,是自己根据这个来封装几个类,然后将运行得到的一连串字符串保存成.dot文件,然后调用

dot -Tpng G.dot -o g.png

就可以绘制成图了,这个想法其实可以的,这样就相当于你能用脚本写出来的,我用代码也能写出来。

不过后来发现其实有相关函数可以调用的:

下面是我自己封装的几个函数

class graphviz_handler():


    # _digraph_str_start="digraph pic { "
    # _digraph_str_context=""
    # _digraph_str_end="}"
    dot = Digraph(comment='Test---')


    #将dot文件转换成png图片
    def generate_PNG(self,test_mark):
        print(self.dot.source)
        self.dot.render('test-output/'+test_mark+'_result.gv', view=True)

    #创建当前页面所有元素,对按钮元素进行初始化
    def element_init(self,sqlite_base,list):
        nameList=self.element_handle(self,sqlite_base,list)
        for elementName in nameList:
            # self._digraph_str_context += elementName+"[shape=circle,lable="+elementName+"] ";
            self.dot.node(elementName,elementName)
            # *实时查看
            self.dot.view()
            # print("%%->"+self._digraph_str_context)



    #处理下元素,获取元素的名字
    def element_handle(self,sqlite_base,list):
        tmp_list = []
        for element in list:
            e = {'location': element.location, 'size': element.size}
            tmp_list.append(e)
        dictList = sqlite_base.get_click_position(tmp_list)
        strList = []
        nameList = []
        for d in dictList:
            strList.append(sqlite_base.position_dict2string(d))
        count=0
        while(count<len(list)):
            nameList.append(list[count].text + "(" + strList[count] + ")")
            count+=1
            #


        return nameList

    #通过id获取元素的所需要的标志name
    def get_elementNmaeByID(sqlite_base,id):
        return sqlite_base.get_elementPositionAndTextByID(sqlite_base,id)


    #创建当前页面
    def cur_page_init(self,pagename):
        self._digraph_str_context += pagename+"[shape=box,lable = "+pagename+"] "
        # print("%%->" + self._digraph_str_context)
        self.dot.node(pagename,pagename,shape="box")
        # *实时查看
        self.dot.view()

    #创建 页面从属关系
    def page_element_connection(self,sqlite_base,page_name,list):
        self.cur_page_init(self,page_name)
        self.element_init(self,sqlite_base,list)

        nameList = self.element_handle(self,sqlite_base,list)
        for element in nameList:
            # self._digraph_str_context+= page_name+"--"+element+"[lable='属于'] "
            # print("%%->**********************" + self._digraph_str_context)
            self.dot.edge(page_name,element)
            #*实时查看
            self.dot.view()
            print(page_name + "--" + element)


    def element_to_page(self,sqlite_base,pagename,elementID,runtimes):
        # self._digraph_str_context+=pagename+"->"+self.get_elementNmaeByID(sqlite_base,elementID)+" "
        # print("%%----->" + self._digraph_str_context)
        self.dot.edge(self.get_elementNmaeByID(sqlite_base,elementID),pagename,label=str(runtimes))
        # *实时查看
        self.dot.view()
        print(pagename+"->"+self.get_elementNmaeByID(sqlite_base,elementID)+"  第"+str(runtimes)+"次")

关键几个是:

from graphviz import Digraph

dot = Digraph(comment='Test---')
self.dot.node(pagename,pagename,shape="box")//节点连接
 self.dot.render('test-output/'+test_mark+'_result.gv', view=True)//生成图片
具体可以看此链接https://blog.csdn.net/a1368783069/article/details/52067404

然后只要把相关函数放到工具里的合适地方就好了


----------------------------------------------------------

那么问题来了,之前一直运行的好好的,后来我不知道搞了什么,就~就~

graphviz.backend.ExecutableNotFound: failed to execute ['dot', '-Tpdf', '-O', 'test-output/Android_1529386737_result.gv'], make sure the Graphviz executables are on your systems' PATH

哇,伤心!

然后这个问题还没解决。

猜你喜欢

转载自blog.csdn.net/qq_25224759/article/details/80759586