Monkey Test 遐思

给公司做了个Symbian Monkey Test工具,结果跑monkey test的任务就一起承担下来。
Monkey Test其实就是个随机输入序列。我想知道这个输入序列长度同发现bug的概率的关系。

现在,一个bug的引发需要一个输入序列串。当这个输入串长度是1的时候,就是说,任意一个随机输入都可能导致bug。这样的软件其实根本不需要测试,直接砍掉重练就好了。因此需要用到monkey测试的程序,一般来说他的bug都是隐藏较深的。假如引发一个bug的输入序列长度是L。则问题就是,一个随机生成的输入序列Input(monkey),它的长度Lm,与引发一个bug所需要的输入序列Input(bug)的长度Lb的关系。

这又涉及到一个问题,就是可能的输入集合。现在我们只考虑手机触屏的话,一台640*320屏幕的手机,触屏输入集合是18万之多。但是考虑到一般的软件都使用控件,而控件一般不会太小而导致用户点击困难,可以用最小能够点击的控件大小作为单位,把屏幕切分开来,每个单元作为一个可能的输入。这就大大减小了输入集合。我们以32*32作为单元的话,一个屏幕会有200个单元格。为照顾一般性,我们设输入集合拥有a个元素。则一个长度为Lm的随机输入串,其可能的组合有aLm之多。

现在我们要考虑的是,这样一个长串中,恰好包含了输入串Input(bug)的可能性。这是一个数列求和。
第一项是Input(monkey)的第0个输入开始恰好匹配Input(bug)的概率。
第二项是从第1个输入开始匹配的概率。但还需减去与第一项重叠的部分。也就是从第0个输入开始,和从第1个输入开始,同时匹配的概率。
第三项是从第2个输入开始匹配的概率。还需减去与第一项重叠的部分以及与第二项重叠的部分。然后再补偿第一、第二、第三项同时匹配的概率。
这样的求和非常复杂,并且是否可能出现匹配的情况,其实是受Input(bug)本身的影响。这里我们作为估算,忽略掉重叠带来的误差,最后会得到一个偏乐观的结果。
于是Input(monkey)恰好包含Input(bug)的概率

p < (Lm-Lb)*a-Lb

当Lm远大于Lb时,我们可近似认为Lm与发现bug的概率成正比。于是Lm增长一倍,则p增大一倍。
由于是简单的线性关系,在Lb不变的情况下,只需简单的增大monkey test的测试序列长度,就能尽可能多地发现bug。因此我们可以预期,当Lm足够大的时候,几乎可以把所有Lb < Llimit的bug都找出来。而这个时候,进一步增长monkey test的长度就变得无效了,因为如果找完了Lb < Llimit的bug,想找到新的bug,一定都是Lb > Llimit的,换句话说,就会导致Lb的增大,而正如我们所见Lb是处于公式的指数上的。增大Lm仅能线性增大找到bug的概率,而增大Lb却导致概率指数级下降,最终导致的结果就是进一步增大Lm却很难找到新的bug了。

既然知道这个道理,我想计算出monkey test大概合适的测试长度。得到最大化的利益。我们根据上述讨论,设a = 200。根据经验bug通常有一个Lb <= 3。则如果我们希望发现一个特定bug的概率超过90%,则有

0.9 < p < (Lm - 3)*200-3

则我们的Lm需要7.2M。假如按照我们常用的设置,一秒钟执行两次操作的话,需要跑超过41天。

这个绝望的估计结果主要原因是200个的输入集合太过巨大了。假如我们仅考虑手机键盘操作的12个键的话,我们可以测试到Lb <= 5,其需要测试的步数大概是220K,按照1秒两个操作需要测试约30个小时,这就在可行范围之内了。

[编辑]这里我仅讨论了想要发现一个特定bug的情况。这是由于我们不知道软件究竟有多少个bug,为保守起见,就按照最悲观的方案来。如果想讨论多个bug的情况,例如10个,则我们仅需令10个bug都找不到的概率降低到0.1以下,则发现每个bug的概率约为0.2。注意到这里其实是对数关系,面对指数级数,这个关系不会对Lm的长度有显著贡献。

0.2 < p < (Lm-3)*200-3

将Lm缩短3.5倍,也无非是从41天降低到九天,仍然是不可接受的长度。当然你会说可以增加同时执行测试的手机数量。但是一旦Lb步长增加1,则立刻就会发现这点缩短其实无意义。[/编辑]

由此也可见,monkey test对于过于复杂以及bug隐藏过深的程序几乎不起作用,如需稳定性测试需要另求他途。