发明内容
本发明的目的就是为了解决上述问题,提供Android应用程序界面自动遍历方法及系统,以Google的uiautomator测试框架为基础,编写程序自动识别Android应用程序每一个界面的唯一标记,将界面作为遍历的结点,并将探测到的可点击的按钮、文本作为连接结点的路径。采用分层的方式进行Android应用程序界面的遍历。最后,遍历界面的数量达到设置的遍历数量值或者Android应用程序被完全遍历完毕时,本次遍历任务完成。
为了实现上述目的,本发明采用如下技术方案:
Android应用程序界面自动遍历方法,包括以下步骤:
步骤(1):初始化Android应用程序界面遍历过程中用到的链表;所述链表包括:组件层次链表、页面标识链表和遍历路径链表;
步骤(2):运行Android应用程序,Android应用程序的主界面被打开;
步骤(3):对Android应用程序的主界面进行遍历;将遍历结果存储到组件层次链表中;
步骤(4):判断组件层次链表中是否有未遍历组件和当前界面的遍历数量是否达到用户在遍历前设定的界面遍历数量的最大值;如果没有未遍历的组件或者已经达到遍历界面的最大值,则遍历完成;否则,进入步骤(5);
步骤(5):获取从Android应用程序的主界面到未遍历组件的触发路径;
步骤(6):依据步骤(5)获取的触发路径,进入未遍历组件对应的界面,采用与步骤(3)同样的遍历方法对未遍历组件对应的界面进行遍历;返回步骤(4)。
进一步的,所述步骤(3)是指对所有可点击的按钮、文字组件进行组合操作,所述组合操作包括点击组件;检测当前是否发生界面跳转,如果发生,则点击返回按键回到触发组合操作之前的界面;如果没有发生界面跳转,则不再点击返回按键,最后将组件信息加入到组件层次链表。
进一步的,所述步骤(3)的步骤包括:
获取当前界面的唯一标识值,然后循环获取当前界面中的所有组件元素,最后依次判断是否可点击,如果可以点击,则触发点击事件,并触发返回事件,从而遍历当前界面中所有可点击组件。
进一步的,所述步骤(3)的步骤包括:
步骤(3-1):接收两个参数,一个参数是当前界面的层数数值,另一个参数是父界面的行号;
步骤(3-2):获取当前界面的唯一标识值;将获取到的当前界面唯一标识值存入到页面标识链表中;
步骤(3-3):设定一个初始值为0的变量n,获取当前界面一个组件编号为n的组件,获取后,n的数值加1;
步骤(3-4):判断组件是否存在;如果组件不存在,则变量n的数值增加1,返回步骤(3-3)继续获取下一个组件;如果组件对象存在,则进入步骤(3-5);
步骤(3-5):判断组件的属性是否为可点击;如果组件对象属性为不可点击,则将编号1,返回步骤(3-3);如果组件对象属性为可点击,则将组件对象信息存储到组件层次链表中;对组件对象发出点击命令,模拟点击组件事件;
步骤(3-6):判断是否退出Android应用程序;如果退出Android应用程序,则遍历程序结束,返回结果;,如果没有退出Android应用程序,则发出返回命令,模拟点击返回键的事件,并同时将组件对象的编号加一后返回步骤(3-3)。
进一步的,所述步骤(5)的步骤包括:
步骤(5-1):接收需要获取触发路径的未遍历组件在组件层次链表中的行号;
步骤(5-2):判断未遍历组件信息中的层数是否为0;当层数值非0时,获取未遍历组件信息中父界面的行号;如果层数值为0,则获取未遍历组件信息中的instance编号,并将instance编号存储到遍历路径链表,将得到的遍历路径链表输出;
步骤(5-3):获取未遍历组件信息中的当前instance编号,并将instance编号存储到遍历路径链表,将步骤(5-2)得到的父界面行号传入步骤(5-1)。
所述步骤(6)的进入未遍历组件对应的界面的步骤如下:
步骤(6-1):接收遍历路径链表;
步骤(6-2):判断链表是否有下一个元素;如果没有下一个元素,则清空该链表,结束;如果有下一个元素,则获取下一个元素的值:组件的instance值;
步骤(6-3):根据组件的instance值点击相应的组件,返回步骤(6-2)。
所述步骤(3-2)获取当前界面的唯一标识值的步骤如下:
步骤(3-2-1):获取当前界面编号为n的组件,n初始值为0;
步骤(3-2-2):判断组件是否存在;如果组件不存在,则返回哈希值字符串,结束;如果组件存在,则获取组件的类名所对应的哈希值;将哈希值与已经存在的哈希值字符串进行拼接,如果哈希值字符串不存在,则将哈希值赋给哈希值字符串;获取编号为n+1的组件返回步骤(3-2-2)。
Android应用程序界面自动遍历系统,包括:
初始化模块:初始化Android应用程序界面遍历过程中用到的链表;所述链表包括:组件层次链表、页面标识链表和遍历路径链表;
Android应用程序运行模块:运行Android应用程序,Android应用程序的主界面被打开;
主界面遍历模块:对Android应用程序的主界面进行遍历;将遍历结果存储到组件层次链表中;
遍历完成与否检测模块:判断组件层次链表中是否有未遍历组件和当前界面的遍历数量是否达到用户在遍历前设定的界面遍历数量的最大值;如果没有未遍历的组件或者已经达到遍历界面的最大值,则遍历完成;否则,进入触发路径获取模块;
触发路径获取模块:获取从Android应用程序的主界面到未遍历组件的触发路径;
未遍历组件对应的界面的遍历模块:依据触发路径获取模块获取的触发路径,进入未遍历组件对应的界面,采用与主界面遍历模块同样的遍历方法对未遍历组件对应的界面进行遍历;返回遍历完成与否检测模块。
进一步的,所述主界面遍历模块是指对所有可点击的按钮、文字组件进行组合操作,所述组合操作包括点击组件;检测当前是否发生界面跳转,如果发生,则点击返回按键回到触发组合操作之前的界面;如果没有发生界面跳转,则不再点击返回按键,最后将组件信息加入到组件层次链表。
进一步的,所述主界面遍历模块包括:
获取当前界面的唯一标识值,然后循环获取当前界面中的所有组件元素,最后依次判断是否可点击,如果可以点击,则触发点击事件,并触发返回事件,从而遍历当前界面中所有可点击组件。
进一步的,所述主界面遍历模块包括:
参数接收子模块:接收两个参数,一个参数是当前界面的层数数值,另一个参数是父界面的行号;
唯一标识值获取子模块:获取当前界面的唯一标识值;将获取到的当前界面唯一标识值存入到页面标识链表中;
组件获取子模块:设定一个初始值为0的变量n,获取当前界面一个组件编号为n的组件,获取后,n的数值加1;
组件存在检测子模块:判断组件是否存在;如果组件不存在,则变量n的数值增加1,返回组件获取子模块继续获取下一个组件;如果组件对象存在,则进入组件属性检测子模块;
组件属性检测子模块:判断组件的属性是否为可点击;如果组件对象属性为不可点击,则将编号1,返回组件获取子模块;如果组件对象属性为可点击,则将组件对象信息存储到组件层次链表中;对组件对象发出点击命令,模拟点击组件事件;
Android应用程序退出与否判断子模块:判断是否退出Android应用程序;如果退出Android应用程序,则遍历程序结束,返回结果;,如果没有退出Android应用程序,则发出返回命令,模拟点击返回键的事件,并同时将组件对象的编号加一后返回组件获取子模块。
进一步的,所述触发路径获取模块包括:
接收子模块:接收需要获取触发路径的未遍历组件在组件层次链表中的行号;
层数判断子模块:判断未遍历组件信息中的层数是否为0;当层数值非0时,获取未遍历组件信息中父界面的行号;如果层数值为0,则获取未遍历组件信息中的instance编号,并将instance编号存储到遍历路径链表,将得到的遍历路径链表输出;
instance编号获取子模块:获取未遍历组件信息中的当前instance编号,并将instance编号存储到遍历路径链表,将层数判断子模块得到的父界面行号传入接收子模块。
所述未遍历组件对应的界面的遍历模块包括:
遍历路径链表接收子模块:接收遍历路径链表;
链表检测子模块:判断链表是否有下一个元素;如果没有下一个元素,则清空该链表,结束;如果有下一个元素,则获取下一个元素的值:组件的instance值;
组件点击子模块:根据组件的instance值点击相应的组件,返回链表检测子模块。
所述唯一标识值获取子模块包括:
组件获取单元:获取当前界面编号为n的组件,n初始值为0;
组件存在与否判断单元:判断组件是否存在;如果组件不存在,则返回哈希值字符串,结束;如果组件存在,则获取组件的类名所对应的哈希值;将哈希值与已经存在的哈希值字符串进行拼接,如果哈希值字符串不存在,则将哈希值赋给哈希值字符串;获取编号为n+1的组件返回组件存在与否判断单元。
本发明的有益效果:
(1)充分考虑到了程序的跨平台可移植性,遍历程序编译成jar包,自动化程序只需将jar包拷贝到Android设备或者Android虚拟机中,通过shell命令即可运行。这样使得无论是Windows平台的自动化程序还是Linux平台的自动化程序都可以直接调用该应用程序界面遍历方法。
(2)将Android应用程序界面中可点击的组件作为遍历的结点,可以使本方法适用于大部分的Android应用程序的遍历工作。
(3)本发明设计了一种Android应用程序界面的唯一标识方法,通过该方法可以快速对程序界面进行识别,防止遍历程序进入死循环。
具体实施方式
下面结合附图与实施例对本发明作进一步说明。
一种Android应用程序界面自动化遍历方法具体工作过程为:
1)初始化Android应用程序界面遍历过程中用到的链表。本方法在工作过程中需要用到3个链表,分别为组件层次链表、页面标识链表和遍历路径链表。
所述组件层次链表的表元素有层数、当前instance编号、父界面行号、遍历标记。
所述层数为组件所在应用程序的逻辑层数,即应用程序是首界面的组件层数为0,通过点击首界面组件跳转的下一层子界面层数为1,以此类推;
所述当前instance编号为一个组件在一个应用程序界面的编号,通过该编号遍历程序可以准确的点击该组件;
所述父界面行号即该组件(A)所在界面被上一层界面中的某个组件(B)在组件层次链表中的位置,其中某个组件(B)是通过点击触发了组件(A)所在的界面;
所述遍历标记为记录当前组件是否已经被遍历。
所述页面标识链表用于存放页面唯一标识代码的。
所述遍历路径链表用于依次存放从程序主界面到遍历界面需点击的组件instance编号。
2)打开需要遍历的应用程序,调用组件遍历模块,对当前应用程序的主界面进行组件的遍历操作。其中组件遍历子模块首先会获取当前界面的唯一标识数值,然后循环获取当前界面中的所有组件元素,最后依次判断是否可点击,如果可以点击,则触发点击事件,并在停顿1秒后点击触发返回事件,以实现遍历当前界面中所有可点击组件的功能。获取当前界面的唯一标识数值时,首先循环获取当前界面中所有存在的组件的类名,然后将类名通过字符串连接的方式连接成一个字符串,最后将生成的一个字符串进行运算获取其哈希值,作为该界面的唯一标识数。
3)检测组件层次链表中是否有未遍历组件和当前的遍历数量是否达到遍历界面的最大值。如果没有未遍历的组件或者已经达到遍历界面的最大值,则遍历完成。否则,调用获取界面触发路径子模块,获取未遍历界面的点击路径。其中获取界面触发路径子模块首先判断目标组件在组件层次链表中的层号是否为0,然后如果非0则递归调用该方法,如果为0,则将组件的id值加入路径链表并返回上一层递归程序。最后获取到从应用程序主界面到指定组件的点击路径。
4)获取到界面触发路径,调用点击指定组件子模块打开需要遍历的界面,调用组件遍历子模块实现对当前界面的探测,遍历工作。其中点击指定组件子模块通过循环的方式读取路径链表中的组件id值,然后依次点击当前界面中的组件。
5)对当前界面遍历完成后,首先触发返回事件,回到应用程序的主界面。再次循环至检测组件层次链表中是否有未遍历组件和当前的遍历数量是否达到遍历界面的最大值的步骤。重复3)-5)的流程。
为了更好的理解本发明,以下给出了本发明更为详细的说明:
图1为本发明实现Android应用程序界面遍历的总体流程图,如图1所示。该方法包括:
步骤110,Android应用程序界面遍历程序开始运行,初始化程序运行时所需的链表,并打开Android应用程序主界面Main Activity。
步骤111,对应用程序主界面的组件进行遍历一次,即对所有可点击的按钮、文字等组件进行一次点击、跳转后的返回操作和将组件信息加入到组件层次链表的操作。
步骤112,查询组件层次链表中的遍历标记,是否还有未遍历的组件。
步骤113,若组件层次链表中没有未遍历的组件,说明遍历结束,程序执行结束。
步骤114,若组件层次链表中有未遍历的组件,则获取从程序首界面到该组件的打开路径,并将该组件对应的遍历标记置为已遍历。
步骤115,对应着获取到的组件打开路径,程序打开点击该组件对应的界面。
步骤116,对打开的程序界面进行遍历一次,方法同步骤110。
图2为本发明实现当前界面遍历的遍历子模块流程图;如图2所示。该方法包括:
步骤120,子流程运行接收两个参数,一个参数是当前界面在程序运行逻辑中的层数,另一个参数是父界面行号即该组件(A)所在界面被上一层界面中的某个组件(B)在组件层次链表中的位置,其中某个组件(B)是通过点击触发了组件(A)所在的界面。
步骤121,调用子程序获取当前界面的唯一标识值。
步骤122,将上一步获取到的当前界面唯一标识值存入到页面标识链表中。
步骤123,获取当前界面一个编号为n的组件对象,n初始值为0。
步骤124,判断该编号的组件对象是否存在。
步骤125,如果该编号的组件不存在,则表示这个界面的组件已经遍历结束,然后触发返回事件,返回到应用程序的首界面。
步骤126,判断该编号的组件属性是否为“可点击”。
步骤127,如果该编号的组件属性为“不可点击”,则将编号n+1返回步骤123。
步骤128,如果该编号的组件属性为“可点击”,则将该组件信息存储到组件层次链表中。
步骤129,对该编号的组件发出点击命令,模拟一次点击组件事件。
步骤130,判断是否退出了应用程序。
步骤131,如果退出了应用程序,则遍历程序结束,返回结果。
步骤132,如果没有退出应用程序,则发出返回命令,模拟一次点击返回键的事件,并同时将编号n+1,返回步骤123。
图3为本发明实现获取界面触发路径子模块的流程图;如图3所示。该方法包括:
步骤140,子流程接收一个参数,即需要获取触发路径的组件在组件层次链表中的行号。
步骤141,判断当前组件信息中的层数是否为0。
步骤142,当层数值非0时,获取当前组件信息中父界面的行号。
步骤143,获取当前组件信息中的当前instance编号,并将该编号存储到遍历路径链表。然后,递归调用该子流程,将步骤142得到的父界面行号传入到递归调用的子流程中。
步骤144,如果当前层数值为0,则获取当前组件信息中的instance编号,并将该编号存储到遍历路径链表。
步骤145,将得到的遍历路径链表作为输出项返回到上一层程序。
图4为本发明实现进入指定界面子模块的流程图。
步骤150,子流程接收一个参数,为遍历路径链表,即如何从程序的主界面通过点击组件的方式打开指定界面。
步骤151,判断链表是否有下一个元素。
步骤152,如果没有下一个元素,则清空该链表。
步骤153,如果有下一个元素,则获取该元素的值,即组件的instance值。
步骤154,根据组件的instance值点击该组件,并返回步骤151。
图5为本发明实现获取界面唯一标识值子模块的流程图。
步骤160,获取当前界面的instance编号为n的组件,如果第一次运行则n为0。instance编号(实例编号即组件编号);
步骤161,判断该编号的组件是否存在。
步骤162,如果该编号的组件不存在,则返回哈希值字符串。
步骤163,如果该编号的组件存在,则获取该组件的类名所对应的哈希值。
步骤164,将该哈希值与已经存在的哈希值字符串进行拼接,如果哈希值字符串不存在,则将该哈希值赋给哈希值字符串。
步骤165,获取界面编号为n+1的组件。
图6为组件层次链表的表结构。
层数,用于表示应用程序组件所在的界面在应用程序的层次位置。即应用程序的主界面层数数值为0,通过点击主界面的组件而跳转到的新界面层数数值为1,以此类推点击层数数值为1的界面中的组件,跳转的界面层数数值为2。若一个界面可以被多个界面点击跳转得到,则以层数数值最小的值作为该界面的层数数值。记录层数用于获取界面触发路径子模块判断当前组件是否在应用程序的主界面(首层界面),如果处在主界面即代表从应用程序主界面直接可以获取到触发路径,如果没有处在主界面,即代表还需递归的查找从应用程序主界面到当前组件的触发路径。
当前instance编号,为一个组件在当前界面中的实例编号,每一个组件在所在的界面中都有一个唯一编号,这个编号从0开始,依次为0,1,2……记录instance编号是用于准确点击界面中的组件。
父界面的行号,假设点击界面(X)中的组件(A)跳转得到界面(Y),界面(Y)中有组件(B)和组件(C)。假设组件(A)在组件层次链表中的行号为(N),则组件(B)和组件(C)在组件层次链表中,父界面行号即为N。
遍历标记,为记录当前界面是否被遍历完成,未被遍历标记为0,已经被遍历标记为1。该标记以防重复遍历已经遍历的界面。
层数的数值存储在组件层次链表中的第一项元素。父界面,即点击界面(X)中的某一组件跳转得到界面(Y),则界面(X)为界面(Y)的父界面。界面的行号即该界面在组件层次链表中的位置。
图7为页面标识链表的表结构。
页面标示链表每一个链表元素只有一个值,页面唯一标识值是用户标识一个应用程序界面的,即每一个界面都对应一个唯一的数值。该数值由界面中所有组件名称的哈希码值构成。
图8为遍历路径链表的表结构。
遍历路径链表每一个链表元素只有一个值,instance值是一个组件在当前界面中的实例编号,每一个组件在所在的界面中都有一个唯一编号,这个编号从0开始,依次为0,1,2……记录instance编号是用于准确点击界面中的组件。遍历路径链表记录着从应用程序的主界面如何一步一步点击到某一个组件的点击顺序。例如某一个组件对应的遍历路径链表中的数值依次为1->4->7,则说明如果想要点击该组件需要在应用程序主界面中点击instance值为1的组件,再点击跳转之后的页面中的instance值为4的组件,再点击跳转之后的页面中的instance值为7的组件就可以了。
如图9所示,Android应用程序界面自动遍历系统,包括:
初始化模块:初始化Android应用程序界面遍历过程中用到的链表;所述链表包括:组件层次链表、页面标识链表和遍历路径链表;
Android应用程序运行模块:运行Android应用程序,Android应用程序的主界面被打开;
主界面遍历模块:对Android应用程序的主界面进行遍历;组件层次链表在遍历时被填充数据;
遍历完成与否检测模块:判断组件层次链表中是否有未遍历组件和当前界面的遍历数量是否达到用户在遍历前设定的界面遍历数量的最大值;如果没有未遍历的组件或者已经达到遍历界面的最大值,则遍历完成;否则,进入触发路径获取模块;
触发路径获取模块:获取从Android应用程序的主界面到未遍历组件的触发路径;
未遍历组件对应的界面的遍历模块:依据触发路径获取模块获取的触发路径,进入未遍历组件对应的界面,采用与主界面遍历模块同样的遍历方法对未遍历组件对应的界面进行遍历;返回遍历完成与否检测模块。
进一步的,所述主界面遍历模块是指对所有可点击的按钮、文字组件进行组合操作,所述组合操作包括点击组件;检测当前是否发生界面跳转,如果发生,则点击返回按键回到触发组合操作之前的界面;如果没有发生界面跳转,则不再点击返回按键,最后将组件信息加入到组件层次链表。
进一步的,所述主界面遍历模块包括:
获取当前界面的唯一标识值,然后循环获取当前界面中的所有组件元素,最后依次判断是否可点击,如果可以点击,则触发点击事件,并触发返回事件,从而遍历当前界面中所有可点击组件。
如图10所示,进一步的,所述主界面遍历模块包括:
参数接收子模块:接收两个参数,一个参数是当前界面的层数数值,另一个参数是父界面的行号;
唯一标识值获取子模块:获取当前界面的唯一标识值;将获取到的当前界面唯一标识值存入到页面标识链表中;
组件获取子模块:设定一个初始值为0的变量n,获取当前界面一个组件编号为n的组件,获取后,n的数值加1;
组件存在检测子模块:判断组件是否存在;如果组件不存在,则变量n的数值增加1,返回组件获取子模块继续获取下一个组件;如果组件对象存在,则进入组件属性检测子模块;
组件属性检测子模块:判断组件的属性是否为可点击;如果组件对象属性为不可点击,则将编号1,返回组件获取子模块;如果组件对象属性为可点击,则将组件对象信息存储到组件层次链表中;对组件对象发出点击命令,模拟点击组件事件;
Android应用程序退出与否判断子模块:判断是否退出Android应用程序;如果退出Android应用程序,则遍历程序结束,返回结果;,如果没有退出Android应用程序,则发出返回命令,模拟点击返回键的事件,并同时将组件对象的编号加一后返回组件获取子模块。
如图11所示,进一步的,所述触发路径获取模块包括:
接收子模块:接收需要获取触发路径的未遍历组件在组件层次链表中的行号;
层数判断子模块:判断未遍历组件信息中的层数是否为0;当层数值非0时,获取未遍历组件信息中父界面的行号;如果层数值为0,则获取未遍历组件信息中的instance编号,并将instance编号存储到遍历路径链表,将得到的遍历路径链表输出;
instance编号获取子模块:获取未遍历组件信息中的当前instance编号,并将instance编号存储到遍历路径链表,将层数判断子模块得到的父界面行号传入接收子模块。
如图12所示,所述未遍历组件对应的界面的遍历模块包括:
遍历路径链表接收子模块:接收遍历路径链表;
链表检测子模块:判断链表是否有下一个元素;如果没有下一个元素,则清空该链表,结束;如果有下一个元素,则获取下一个元素的值:组件的instance值;
组件点击子模块:根据组件的instance值点击相应的组件,返回链表检测子模块。
如图13所示,所述唯一标识值获取子模块包括:
组件获取单元:获取当前界面编号为n的组件,n初始值为0;
组件存在与否判断单元:判断组件是否存在;如果组件不存在,则返回哈希值字符串,结束;如果组件存在,则获取组件的类名所对应的哈希值;将哈希值与已经存在的哈希值字符串进行拼接,如果哈希值字符串不存在,则将哈希值赋给哈希值字符串;获取编号为n+1的组件返回组件存在与否判断单元。
上述虽然结合附图对本发明的具体实施方式进行了描述,但并非对本发明保护范围的限制,所属领域技术人员应该明白,在本发明的技术方案的基础上,本领域技术人员不需要付出创造性劳动即可做出的各种修改或变形仍在本发明的保护范围以内。