Page 111 - 《软件学报》2025年第5期
P. 111

郝蕊 等: 基于事件标记的多粒度结合安卓测试序列约减                                                      2011


                                               end  之间的所有出边与入边, 这里我们还需保证入边事件一定发生在出边
                 环路, 其首先选取节点      v 上落在   start  、
                 事件之前, 才能检测到环路        (第  14–16  行). 接下来, 依次遍历出边集    E out  与入边集  E in  , 得到事件对  (e out ,e in ) , 即可得
                 到由  e out  到  e in  之间的所有事件组成的最长环路.
                 算法  1. 环路检测.

                                  G,T s  )
                 1. Function findLoops(
                     L ← ∅;  //待返回的结果环路集合
                 2.
                 3.  for each event    e  on path   T s   do
                                       e 的源节点
                 4.     v s ← e.source;  // 事件
                 5.     start ← 0;
                        v s , v initial   then
                 6.   if
                 7.       start ← v s .lastIncomingEvent.id;  //获取源节点的入边集中的最大  id
                 8.     end ← e.id;
                                                            v s  作为起始及终止节点的环路
                 9.      L v s  ← findNodeLoops(  G,v s , start,end ;  // 检测以
                                                   )
                 10.   insert all loops in    L v s    into   L;
                 11.  return   L;
                 12. Function findNodeLoops(  G,v, start,end )
                      L ← ∅;  // 待返回的结果环路集合
                 13.
                 14.     E out ← filter(  G.outgoingEvents(v), start,end ;  // 选取  id 在  [start,end] 之间的出边
                                                       )
                 15.     start ← min(   E out ;  // 重新设定   start 为所有出边中的最小  id
                                   )
                                                                  [start,end] 之间的入边
                 16.     E in ← filter(  G.incomingEvents(v), start,end ;  // 选取  id 在
                                                       )
                 17.  for    i  in   [0,E out .size)  do // 此处   E out .size 不大于  E in .size
                 18.     e out ← E out .item(i);
                 19.     e in ← E in .item(i);
                 20.     l ← {e k : e out .id ⩽ e k .id ⩽ e in .id};  // 环路  l 包含  e out  到  e in  之间的所有事件
                 21.   insert   l  into   L;
                 22. return   L;

                 3.3   环路标记
                    状态跳转图中包含的环路有时候会达到几十甚至上百, 此外, 有时需要在多个环路的共同作用下程序崩溃才
                 会触发, 因此对所有环路及它们的组合进行验证是一项非常耗时的工作. 在本文中, 我们采用对标记环路重要性的
                 策略, 将与程序崩溃触发最有关联的环路单独进行标记, 并在后续最短测试路径搜索过程中采用由高到低的方式
                 依次对不同重要性环路进行搜索, 降低算法开销.
                    我们将环路分为      3  个层次: 重要环路    (IMPORTANT)、普通环路    (NORMAL)、次要环路     (MINOR). 一条环路的
                 优先级由此环路中所有事件的最高优先级决定. 其中次要事件主要是与应用逻辑无关的按键操作                                 (KeyEvent), 比
                 如调整设备声音大小、屏幕亮度.
                    在本文中, 我们关注      3  个方面的重要事件, 分别是执行环境改变事件、生命周期相关事件、数据流依赖相关
                 事件. 其中执行环境改变事件是指改变设备网络状态、位置服务状态、信号状态、电池状态、传感器数据设置
                 等, 这些事件可直接通过对测试脚本中事件格式解析的方式进行识别.
                    安卓系统通过返回栈机制管理不同应用的活动, 活动在入栈、出栈过程中伴随了一系列生命周期状态的变
                 化, 安卓组件需要在生命周期状态改变时调用不同回调函数来对布局、数据、资源进行妥善处理. 安卓中最常见
                 的  Activity 活动组件提供了  7 个与生命周期管理相关的回调函数, 例如活动创建、暂停、销毁、重启等, 而                      Fragment
   106   107   108   109   110   111   112   113   114   115   116