【测试分析】基于状态的测试
前言
这一篇比较特别,内容提供者是我的好朋友jingle——专业的iOS测试工程师。
文章的原链接请点击这里,iOS测试的同学们也可以扫码关注她的微信公众号,里面有些她自己总结的iOS测试经验。上码:
什么叫基于状态的测试
基于状态的测试,是一种基于模型的测试,常用于事件驱动的系统中,这些系统往往是实时系统,比如数字技术和硬件电路。实际中的系统,比如下面这些通常会用到状态机:
1)作业处理系统
2)ATM机
3)界面处理程序
基于状态的测试,也是一种黑盒测试设计技术,所涉及的测试用例用来执行(遍历)有效和无效的状态转换,当有一系列的事件和条件,且对特定事件/条件的处理又取决于曾经发生过的事件和条件时,比较适合使用基于状态的测试技术。
模型
在状态机主要分为两类,一类是输出只和状态有关与输入无关,称为Moore状态机;另一类是输出不仅和状态有关还和输入有关,称为Mealy状态机。
1)Mealy状态机
基本概念:
--node(节点):代表系统的状态
--link(链接):代表节点之间的关联
2)Moore状态机
节点:代表系统中发生的事件
3)优劣
Mealy状态机因为有以下几个特点更简单的运用在实际工作中:
1)更接近于实际执行情况
2)有较少的状态,且
3)状态稳定
4)当状态图变得更加复杂的时候可以比较简单的重复事件
5)在表中更加容易去展现状态图
书中讲到,在拿到我们待分析的对象后,首先需要描述该对象的所有状态,其次,是描述各个状态之间的转换以及转换过程中发生的事件。其中,整个过程中最难的也是最有意思的部分是设计状态机模型。但是一般该过程会包括以下四个部分:
1)列出分析对象所包含的各种状态
2)列出不同状态之间的转换
3)确定引起各个转换的事件
4)分析各个转换过程中发生的事件
一个简单的例子
书中举了一个ATM机的例子来说明是如何设计状态机的,以及由状态转换图怎样变为最终的测试用例的。
a.首先根据第二节中提到的4个基本步骤设计ATM机的状态转换图
1)分析各种状态:未插卡状态,插卡请求PIN状态,获取到PIN状态 (待转换)
2)为不同的状态列出其之间的转换
3)引起各个状态转换的事件
插卡
输入正确的PIN码
输入错误的PIN码
输入正确的转换条件
输入错误的转换条件
选择退出
4)转换过程中发生的事件
请求新的PIN码
请求新的卡片
请求新的转换
返回钱,卡片,交易凭证
b.根据上面分析的结果,画出状态转换图
图中最后一个节点是V3,而不是V1(从书中直接截的图)。
c.根据状态图编写基本的测试用例
有了状态转换图,我们就可以根据节点以及节点之间的链接编写测试用例了,测试用例就是从一个状态到另一个状态,然后遍历两个状态间的路径。那么,问题来了,怎么覆盖状态与状态之间的所有路径呢?显然,使用人工的方法是最容易想到的,但是不会漏掉某一条路径吗,尤其是当状态机非常复杂的时候?幸运的是,现成的理论中有很多种方法来解决这个问题,比如下面的覆盖状态图的方法:
1)覆盖典型路径
2)旅行推销员路径
3)中国邮递员路径
4)基于风险去覆盖
5)覆盖所有状态转移长度
6)离开一个状态的所有方法
7)不产生状态转换的事件
2)和3)这两种方法也是数学界里比较典型的两个问题,感兴趣的可以去Google搜索下。
当然,你也可以先使用最简单的办法创建出状态转换表,如下表:
该表的创建方法为:
1)列出状态转换图的所有状态,本例子ATM的状态为V1,V2,V3
2)列出状态转换图中所有事件/条件的组合
3)创建表格,对于每个状态,将其与每个事件/条件组合填入表中
通过上面的内容,应该对状态机以及怎么设计状态机有了一定的认识,下面一起来学习下怎么通过状态机来设计简单的测试用例,以及如何扩展更加全面的测试用例。
创建测试用例
根据刚才生成的表,设计测试用例,去覆盖到上表所示的所有状态转换。设计的测试用例如下:
第一条case:
1)插入卡片(状态V1)
2)输入错误密码(状态V2)
3)输入正确密码(状态V3)
4)等待转换(状态V3)
5)取出钱和卡片(状态V1)
第二条case:
1)输入错误密码(状态V1)
2)取走被拒绝的卡片(状态V2)
第三条case:
1)插入卡片(状态V1)
2)输入错误的密码(状态V2)
3)输入错误的密码(状态V2)
4)输入错误的密码(状态V2)
5)卡片弹出,回到初始状态(状态V1)
这三条case,可以覆盖到状态转换表中的所有转换,其中,在第一条case中覆盖了b,c,e,g这4个转换,第二条case覆盖了a转换,第三条case覆盖了转换d。但是这三条case是否覆盖了所有状态以及转换呢?显然,没有覆盖完全。
转换对
为了得到更好的覆盖度和精确度,可以覆盖两个转换所涉及到的所有组合,书中提到了1-切换覆盖,这个概念的理论依据是N-1切换覆盖,其定义是: 要求长度小于等于N的每一条状态序列至少有一个对应的测试用例。例如:要求覆盖所有长度为1的转换,则N-1切换覆盖即为0-切换覆盖。有了理论依据,我们就可以根据上一篇文章得到的状态转换图来设计扩展的状态转换表。如下表:
这里说一下这个表是怎么得到的?该表中共有5列,第一列是状态转换图中的三个状态,第二列是对每个状态节点出去的边和回来的边(参考图论中的节点的出度和入度),第三四五列是从状态节点出去或者进来的边(即状态机中的转换),除此之外,每个状态节点都有一行数据(第三行),该行数据是通过In那一行指向out那行得到的,即对应一个转换。如下图所示:
从In节点c到Out节点e和a(红色箭头和红色框框所示),便形成了转换15:c-e和16:c-a,同理,其他的转换也是这么来的。
有了转换对得到的扩展状态转换表后,就很容易得到扩展版的转换表,如下图:
由之前的只有7行的状态转换表到上表16行的状态转换表,很明显扩展了不少,然后我们只需要设计足够的测试用例来覆盖这些状态转换就行了,相比之前的7行状态转换,这个显然做到了高覆盖度和高精确度。
小结
从简单的几条case到扩展版的状态转换表,我们要做的就是根据状态转换图来尽可能多的覆盖图中所示的各种转换(其实,这里我们可以把状态转换图看成一个普通的图,然后利用图论中的知识来进行覆盖就会显得比较简单了)。
学习了状态机,对我们测试而言,需要自己去分析被测对象是否适合用状态机的方法去进行测试?如果适合的话,怎么去设计被测对象的状态图?这些就需要因被测对象而异了。
个人认为,基于状态的测试适用于:被测对象拥有多个状态,且各个状态之间的转换由事件来触发,且各状态之间的转换还可能导致一些动作action的发生。其难点在于:如何设计被测对象的状态转换图?如何根据状态转换图设计测试用例?这需要各位在实际工作中慢慢体会了。