基于模型的自动化测试工具:GraphWalker

来源:转载


一、概述

GraphWalker就是一个基于测试模型的用例生成工具。它主要应用于FSM, EFSM模型。可以用来它可以直接读取FSM, EFSM图形模型、json模型、生成测试用例。


二、背景知识

要了解GraphWalker首先要了解MBT是什么。


MBT中文名称为基于模型的测试, 基于模型的测试属于软件测试领域的一种测试方法。MBT步骤如下:首先由被测系统(SUT, system under test )的一些(通常是功能)方面描述,构建出被测系统的模型。再根据模型或模型中的一部分部分生成测试用例。进而进行软件测试。


2.1


模型(Model)



模型的目的就是用来为构造测试用例而进行的被测系统描述。


在构造模型的这个阶段就可以已经发现许多问题。


模型的关键:



高度抽象


模型还包括被测系统的预期输出。



两个主要方面:



设计模型


测试模型



MBT中模型通常有下列几种:



前置后置条件模型: Pre and post condition models (State based, OCL)


基于转换的模型: Transition based models (FSM, EFSM)


随机模型:Stochastic models (Markov chains)


数据流模型: Data-flowmodels(Lustre)



模型验证:



语法


行为



FSM举例:


一个测试模型可以由箭头和节点组成如下图所示。



一个箭头,代表了一次测试动作;


一个节点,代表一次测试验证。




2.2


测试需求选择

Test requirements selection


目的:


指导测试用例生成器( test generation)如何生成用例。


测试需求选择包含3方面:


1. 模型中的目标(结束条件)


2. 覆盖准则(路径生成准则)


状态覆盖


转换覆盖


3. 行走算法


随机行走


覆盖引导



2.3


测试用例生成


Test generation

按模型及测试需求选择来生成测试用例。GraphWalker就是完成这部分工作的一个开源的java工具。




2.4


测试具体化


Test concretization

从测试套件到可执行级别,可以自己实现插件完成这部分功能。将测试用例转化成可执行脚本。




2.5


执行测试


Test execution

执行测试,并比较预期结果。



三、GraphWalker能做什么

GraphWalker就是一个基于测试模型的用例生成工具,完成上图中Test generation的工作。给出一个测试模型及测试需求选择,GraphWalker能生成相应测试路径。由这个测试路径,可以用来执行你的测试脚本。它主要应用于FSM, EFSM模型。可以用来它可以直接读取FSM, EFSM图形模型、json模型、生成测试用例。


四、通过GraphWalker建模

模型的目的是表达被测系统的预期行为。为此,我们使用有向图,其中顶点(或节点)表示一些期望的状态,并且边(弧,箭头,过渡)表示为了实现期望的状态需要做的任何动作。


例如,让我们来看一个需要验证的网站,然后才能访问网站内容。使用有向图设计测试可能如下所示:



4.1


顶点(Vertex)



顶点表示我们想要检查的预期状态。在任何实现代码/测试中,你可以通过断言或者数据校验改结果。



一个顶点称为节点,通常表示为一个框。


GraphWalker不在乎顶点的颜色或形状。




4.2


边(Edge)



表示从一个顶点到另一个顶点的方法。这是为了达到下一个状态需要做的任何动作。它可以选择一些菜单选项,单击按钮等测试动作。



GraphWalker只接受单向有向边(箭头)。


GraphWalker不关心边有什么颜色或宽度。




4.3


建模规则



Start顶点

start顶点不是必需的。


如果使用,则必须有 1 个(且只有 1 个)顶点名称为: start.


从 start 顶点出发只能有 1 个边。


start顶点不会包括在任何生成的测试路径中,它 只表示一个开始位。



顶点或边的名字(name)

名称是第一个单词,位于标签中边或顶点的第一行。



标签(Lable)

标签是点 或边上的 所有 文字描述。



守卫(Guards)仅用于Edge

守卫 guard 是一种只与边相关的机制。他们的角色与 if 语句相同,并且使边有资格或者没有资格 被 访问。


守卫 guard 是一个用方括号括起来的 JavaScript 条件表达式只有 一个。



[loggedIn == true]


上面意味着如果属性 loggedIn 等于 true ,则边是可访问的。


操作(Action)仅用于Edge

动作是仅与边相关联的机制。这是我们要在模型中执行的 JavaScript 代码。它放在正斜杠之后。 Action 可以 有多个, 每个语句必须以分号结尾。



/loggedIn=false; rememberMe=true;



ac tion 是动作代码,它的 执行结果将 作为数据传递给守卫。



示例:



此示例说明 Action 和 Gu ard如何工作。



让我们从 Start 顶点开始:


e _Init/validLogin=false;rememberMe=false;


边缘的名称是 e_Init ,后跟一个正斜杠,表示从该点开始直到行尾的文本是 [action] 代码。该操作初始化 2 个属性: validLogin 和 rememberMe 。


当我们走过上边缘时,我们到达 v_ClientNotRunning 顶点。这个顶点有 2 个边沿,都有 Guards 。由于 validLogin 和 rememberMe 在这一点上被初始化为 false ,因此只有一个边可以用于步行:边 e_StartClient 具有顶点 v_LoginPrompted 作为目的地。


假如,我们已经遍历边 e_ToggleRememberMe 和 e_ValidPremiumCredentials ,并再次到达顶点 v_ClientNotRunning ,现在 GraphWalker 选择将 选择 具有顶点 v_Browse 作为目标的另一条边 e_StartClient 。



这说明了如果我们需要这样做,我们如何能够通过图表来指导和控制模型执行 路径。


模型中的关键字

在模型中使用关键词以增加功能和可用性。


Start -这在顶点中用于表示开始顶点。每个模型只有一个起始顶点。


BLOCKED -包含此关键字的顶点或边将在生成路径时排除。如果它是一个边,它将简单地从图中删除。如果它是一个顶点,顶点将被删除与其内外边缘。


SHARED -此关键字仅用于顶点。这意味着 GraphWalker 可以跳出当前模型,到任何其他模型到具有相同 SHARED 名称的顶点。 语法是: SHARED : SOME_NAME


INIT - 只有一个顶点可以有这个关键字。在模型中使用数据时,需要初始化数据。这就是这个关键字。允许在更多的顶点中使用 INIT 而不只是一个。 语法是: INIT : loggedIn = false; rememberMe = true;


REQTAG -只有一个顶点可以有这个关键字。调用以根据需求标记 vertices 。 语法是: REQTAG : String



多模型

GraphWalker可以在一个会话中使用几个模型。这意味着在生成路径时, GraphWalker 可以选择跳出一个模型到另一个模型。当将不同的功能分为多个模型时,这是非常方便的。


控制模型之间跳转的机制是关键字 SHARED 。让我们看一个例子。考虑这 4 个模型:





多模型 offilne 运行举例:



java -jar graphwalker-cli-4.0.0-SNAPSHOT.jar -d all offline -m Model_A.graphml random(edge_coverage(100)) -m Model_B.graphml random(edge_coverage(100)) -m Model_C.graphml random(edge_coverage(100)) -m Model_D.graphml random(edge_coverage(100)) –o



所有模型都加载到 GraphWalker 中,第一个模型(模型 A )是路径生成开始的地方。


当路径生成到达模型 A 中的顶点 v_B 时,它必须考虑关键字 SHARED : B .. 这将告诉 GraphWalker 使用相同的名称搜索所有其他模型的同一个关键字: B. 在我们的例子中,只有一个,它在模型 B 中。现在 GraphWalker 决定是跳出模型 A ,进入模型 B 中的顶点 v_B ,还是留在模型 A 中。这个决定是基于随机的。


此外,如果路径生成在模型 B 中执行,并且它到达顶点 v_B ,则 GraphWalker 可以跳出模型 B ,回到模型 A 中的顶点 v_B 。



多模型特性

多 模型 之间 的 数据 不通用。 如 上述模型,虽然模型 A与 模型 B用 相同变量eB ,但 在不同模型间跳转时。 M odelA 中 的 e B , 与 M odelB 中的 eB 是 不同变量。


多 模型一起启动时,所有模型一 起进行 初始化。


多 模型之间跳转,相当与 G raphWalker 自动 在 SHARD状态 之间。建立 2条虚拟 边, G raphWalker 将根据算法 选择是否前往shard 状态 。


多 模型之间跳转, 以 SHARED :标识 的名称做 作为 查找对象 ,它 要求为一个非空字符串。




五、路径生成器和结束条件

路径生成器连同停止条件将决定当通过模型生成路径时使用什么策略,以及何时停止生成该路径。路径发生器可以彼此连接。可以使用逻辑或, AND,||,&&使用多个停止条件。


5.1


路径生成器


生成器是决定如何遍历模型的算法。不同的生成器将生成不同的测试序列,并且它们将以不同的方式遍历模型。多个发生器可以串联。


random( some stop condition(s) )


以完全随机的方式浏览模型。也称为“醉汉走路”或“随机步行”。该算法通过随机从顶点选择出边,并且在下一个顶点时重复此过程。


quick_random( some stop condition(s) )


尝试运行通过模型的最短路径,但以快速的方式。这是算法的工作原理:


1. 选择一个尚未被随机访问的边。


2. 使用 Dijkstra 算法选择到该边缘的最短路径


3. 走该路径,并将所有执行的边标记为已访问。


4. 当在步骤 1 中达到选定的边缘时,从头开始,重复步骤 1-> 4 。


5. 该算法对于非常大的模型工作良好,并且生成合理的短序列。缺点是当与 EFSM 结合使用时。该算法可以选择被守卫 block 的路径。


a_star( a stop condition that names a vertex or an edge )


将生成到特定顶点或边的最短路径。


shortest_all_paths ==> (Not released yet)


将计算并生成通过模型的最短路径。每个边缘的成本设置为 1 .不建议使用此算法,因为对于较大的模型,并且使用模型( EFSM)中的数据,将需要相当长的时间来计算。


5.2


结束条件



结束 条件


edge_coverage( an integer representing percentage of desired edge coverage )


边覆盖率达到某个值时,模型遍历结束。停止标准是一个百分比数字。当在执行期间达到所穿过的边的百分比时,停止测试。如果一个边被遍历超过一次,当计算百分比覆盖率时,它仍然计为 1


vertex_coverage( an integer representing percentage of desired vertex coverage )


顶点覆盖率达到某个值时,模型遍历结束。停止标准是一个百分比数字。当在执行期间达到所遍历的顶点的百分比时,停止测试。如果顶点遍历超过一次,当计算百分比覆盖率时,它仍然计为 1。


requirement_coverage( an integer representing percentage of desired requirement coverage )


需求覆盖率达到某个值时,模型遍历结束。停止标准是一个百分比数字。当在执行期间达到所需求的百分比时,测试停止。如果需求遍历超过一次,在计算百分比覆盖率时仍会计为 1。


dependency_edge_coverage( an integer representing dependency treshold )


高于依赖阈值的边都被覆盖时,模型遍历结束。每个边可以设置一个依赖值dependency( 0 -100之间的百分比数字)。停止标准是一个百分比数字。当在执行期间,所有高于或等于依赖值边被遍历完全时,停止测试。如果一个边被遍历超过一次,当计算百分比覆盖率时,它仍然计为 1。


reached_vertex( the name of the vertex to reach )


停止标准是指定的顶点。当在执行期间到达顶点时,测试停止。


reached_edge( the name of the edge to reach )


停止标准是指定的边。当在执行期间到达这条边时,测试停止。


time_duration( an integer representing the number of seconds to run )


停止标准是表示允许测试发生器执行的秒数的时间。 请注意,时间与整个测试的执行进行比较。例如,这意味着,如果你有:


l 2个模型


l 2 个 模型中存在共享状态


l 两者都具有设置为60秒的时间停止条件


l 两种型号将在 60 秒后停止执行。即使一个模型没有访问过


length( an integer )


条件是一个数字,表示由生成器生成的(边- 顶点 )对的总数。例如,如果数字是110 ,测试序列将是 220 个 do-check 动作(包括 110 对边和顶点)。


never


这种特殊的停止条件永远不会停止。



5.3


举例



举例:



六、GraphWalker工作方式

6.1


GraphWalker提供3种工作方式



作为第三方库,可被java测试程序直接调用。


作为可执行程序,以offline模式,加载model,直接运行。


作为可执行程序,以online模式,作为service,提供服务。



6.2


作为java第三方库



作为第三方库,被java测试程序调用


Java测试程序调用GraphWalker时,可以直接继承GraphWalkerorg.graphwalker.core.machine.ExecutionContext 类。该类成员函数,可以配置在guard、action中调用。在ExecutionContext类初始化时中,以将所有类成员函数转化成了javascript函数调用,存在Context的js引擎中。函数名完全一致。作用是使原本的js引擎可以调用java代码。


以一个maven工程创建的测试举例。


1. 新建一个目录,存放测试程序。


2. mkdir -p gw_test/src/test/java/


3. cd gw_test


4. 创建文件 src/test/java/ExampleTest.java 复制以下代码到.java文件中。




同时,创建pom.xml, 复制以下代码。pom.xml文件描述了测试程序用到的第三方jar包。可以看到,GraphWalker被包含在其中。如果本地没有该jar包,maven会自动从网上下载。



执行测试程序

运行mvn test。执行测试程序。Maven先下载了所需的jar包后,开始测试。


测试程序做了什么

首先,我们扩展类ExecutionContext,它是 GraphWalker需要的执行上下文的接口。然后将Context传递给SimpleMachine的构造函数。创建了一个GraphWalker的执行器。


以一个测试用例为例:



它的执行过程可以解释如下:


1. 创建start节点


2. 创建图形或模型。


3. 向模型中添加边。


4. 这个边命名为:edge1


5. 向这条边添加守卫guard。 guard是条件表达式,这个guard将执行类成员函数isTrue()得到返回值。如果返回值为true,则边可以被访问以执行,否则不执行。


6. 设置这条边的起点。这里设置的起点为start顶点。


7. 将start顶点命名为:vertex1。


8. 创建一个新的顶点,并将其设置为edge1这条边的目标顶点。


9. 刚建立的顶点命名为:vertex2。


10. 为edge1这条边添加一个操作Action。该操作是在遍历到edge1边时执行的JavaScript代码,调用函数myAction。


11. 构建模型(使其不可变),并将其提供给Context。


12. 创建一个路径生成器,并指定停止条件,并将其提供给Context。


13. 将start顶点设置为模型执行的起点。


14. 创建一个GraphWalker的执行器machine,把Context传递给machine


15. 只要路径生成器的停止条件未满足,hasNext将返回true。


16. 执行模型的下一步。



6.3


以offline模式,加载model



作为可执行程序,以offline模式,加载model,直接运行。

见GraphWalker命令行,offline



6.4


以online模式,作为service


作为可执行程序,以online模式,作为service,提供服务


见GraphWalker命令行,online


七、GraphWalker命令行

java -jar graphwalker-cli-3.4.2.jar


7.1


Global options



全局选项会影响所有命令。一些选项,如版本,直接退出程序。



–debug, -d



Sets the log level: OFF, ERROR, WARN, INFO, DEBUG, TRACE, ALL. Default: OFF



–help, -h



Prints help text



–version -v



Prints the version of GraphWalker



7.2


Offline



离线意味着生成测试序列一次,以后可以自动运行。或者,只是生成序列以证明具有路径生成器的模型与停止条件一起工作。


java -jar graphwalker-cli-3.4.2.jar GLOBAL_OPTIONS offline OPTIONS -m <model-file> "GENERATOR(STOP_CONDITION)"



–json, -j



返回数据格式为json, 默认true



–model, -m



模型文件,一个 graphml 文件,后面跟着路径生成器及结束条件。这个选项可以出现多次。



–unvisited, -u



加上这个选项将打印出模型中未访问到的元素,默认 false.



–verbose, -o



打印更多细节,默认false.



7.3


Online



在线测试意味着基于模型的测试工具直接连接被测系统并进行动态测试。 GraphWalker将作为WebSocket(默认)或HTTP REST服务器启动。



–json, -j



返回数据格式为json,默认true



–model, -m



模型文件,一个 graphml 文件,后面跟着路径生成器及结束条件。这个选项可以出现多次。这个选线在RESTFUL模式(-s RESTFUL)下有效、在websocket模式(-s WEBSOCKET)下无效。



–port, -p



GraphWalker作为service 的端口号,默认8887



–service, -s



选则GraphWalker作为service的启动模式. WEBSOCKET [默认], 或者 RESTFUL


默认WEBSOCKET。当 Websocket 模式被选择了 -m 选项无效。



–start-element, -e



选择元素作为开始元素(第一个模型中)。默认start顶点。



–unvisited, -u



加上这个选项将打印出模型中未访问到的元素,默认 false.



–verbose, -o



打印更多细节,默认false.



八、Restful或WebSocket服务的区别
运行GraphWalker作为Restful或WebSocket服务有什么区别?

8.1


Restful




同步,这使得客户端易于实现。


只能服务1个客户端。



该服务当时只处理一个会话。模型可以使用REST加载API调用上传,也可以在服务启动时的命令行中加载。


命令行举例:


启动 GraphWalker REST service 在默认端口 8887, debug level设置为 ALL.


java -jar graphwalker-cli-3.4.2.jar --debug all online --service RESTFUL


启动GraphWalker REST在端口9999 不进行debug


java -jar graphwalker-cli-3.4.2.jar online --service RESTFUL --port 9999


启动GraphWalker REST, 在默认端口 8887, debug level设置为full, 服务启动是加载模型ShoppingCart.graphml


java -jar graphwalker-cli-3.4.2.jar -d all online -s RESTFUL -m ShoppingCart.graphml "random(edge_coverage(100))"



8.2


Web Socket




异步,这使得客户端实现有点复杂。


可以同时为多个客户端服务



该服务将处理多个连接。每个连接都将有一个唯一的会话。必须使用Websocket start API调用来上传模型。它不会在命令行上加载任何模型


命令行举例:


启动 GraphWalker Websocket service在默认端口8887 and debug level 设置为 ALL.


java -jar graphwalker-cli-3.4.2.jar --debug all online


启动GraphWalker Websocket service 在端口9999 with不进行debug.


java -jar graphwalker-cli-3.4.2.jar online --port 9999 --service WEBSOCKET



九、Web Socket API接口

9.1


start



Websocket 消息命令start用于加载模型并启动服务。模型必须对GraphWalker模型使用JSON格式 。


Request

加载和启动模型的请求示例。模型在gw3标签内



Response

如果请求成功 “success” 为 “true” .




9.2


hasNext



Websocket 消息命令hasNext用于询问GraphWalker是否有任何元素在模型中执行。如果满足当前模型的所有停止条件,则对hasNext属性的响应将返回false。


Request


Response

如果请求成功 “success” 为 “true” .



9.3


getNext



Websocket 消息命令getNext用于从路径生成中获取下一个元素。GraphWalker将给定路径生成器,计算下一个元素应该是什么,并在模型的执行中向前进一步。 在响应中返回元素名称。


Request


Response

如果请求成功 “success” 为 “true” .




9.4


getData



Websocket消息命令getData用于询问GraphWalker当前模型的当前各个变量的数据值


Request


Response

如果请求成功 “success” 为 “true” .




9.5


visitedElement



每当getNext发生时, GraphWalker将发送visitedElement消息给client。此消息中的信息表示了模型遍历的进度。



Message




十、REST API接口

10.1


load



Rest调用load以JASON格式上载模型,并使用新测试重 置GraphWalker。


POST Request

http://service-host:8887/graphwalker/load + json graph file


Response

请求成功,返回ok.




10.2


hasNext



如果有更多的元素要获取, Rest将调用hasNext查询服务。如果是,则尚未达到停止条件的满足。


GET Request

http://service-host:8887/graphwalker/hasNext


Response

如果请求成功,“result”将是“ok”。如果有更多的元素要获 得,hasNext将是true。




10.3


getNext



getNext 用于从路径生成中获取下一个元素。GraphWalker将给定路径生成器,计算下一个元素应该是什么,并在模型的执行中向前一步。 在响应中返回元素名称。


GET Request

http://service-host:8887/graphwalker/getNext


Response

如果请求成功,“ result”为“ok” ” . currentElement 返回元素名




10.4


getData



getData用于询问GraphWalker当前模型的当前各个变量的数据值。


POST Request

http://service-host:8887/graphwalker/getData


Response

如果请求成功,“ result”为“ok” ” . data 中返回各个变量的当前值。




10.5


setData



用来设置当前模型中变量值


POST Request

http://service-host:8887/graphwalker/setData/


Response

如果请求成功,“result”为“ok” .




10.6


restart



模型重置为其初始状态。


PUT Request

http://service-host:8887/graphwalker/restart


Response

如果请求成功,“result”为“ok”.




10.7


fail



会终止测试会话的路径继续生成


PUT Request

http://service-host:8887/graphwalker/fail/String%20to%20explain%20the%20failure



Response




10.8


getStatistics



调用getStatistics将获取会话的当前统计信息


POST Request

http://service-host:8887/graphwalker/getStatistics


Response

如果请求成功,“result”为“ok” .




十一、GraphWalker源码及构建

11.1


编译GraphWalker前准备工作


· Install Java JDK 7 or 8


· Install Maven


· Git


11.2


获取源码


1. 下载 源码


2. 通过git获取源码


git clone https://github.com/GraphWalker/graphwalker-project.git


11.3


Build GraphWalker jar包


cd graphwalker-project


mvn package -pl graphwalker-cli -am


可能遇到编译不过的情况。处理方法:


1. 先clean一下,再重新编译。


mvn clean


mvn package -pl graphwalker-cli –am



mvn clean


mvn package -pl graphwalker-cli -am


2. GraphWalker中为每个工程写了大量的单元测试。如果单元测试不过,也会造成mvn编译不过去。这时,可以先注释掉某些test。Test目录在每个工程对应src/test/java目录下。


正确编译后,显示:


Build完成后,jar包目录:


graphwalker-cli/target/graphwalker-cli-3.4.2.jar


11.4


GraphWalker 工程结构





graphwalker-cli

GraphWalker Command Line Interface


graphwalker-core

GraphWalker 工具 核心



A lgorithm:


路径 选择算法 具体 实现 所在 位置。


Condi t ion:


路径 遍历结束条件


E vent:


GraphWalker 执行 到 getNext() 命令 ,获取 nextElement 是 ,将触发两个 事件 : BEFORE_ELEMENT, AFTER_ELEMENT 。


Observer 用户 捕获 事件 ,进行处理 。


G e nerator:


根据调用 算法生成路径。


M a chine:


GraphWalker 执行器 。 J s 执行引擎、模型执行上下文环境、模型存储,都在这里。


M o dle :


模型 类


graphwalker-dsl

y ed 文件 解释器, 用户 解析 .graphml 文件


graphwalker-io

i o 转换。用 于解析各种 格式模型输 入 。 Json 、 java 、 yed 、 dot 。 以及 将 已有模型转换成各种格式模型输出 Json 、 java 、 yed 、 dot 。


graphwalker-java

Gra phWalker 提供 的 的 java annoation 功能 。 及 测试 report 输出 功能。


graphwalker-plugin

为 Gra phWalker 作为 mavenplugin 提供 支持。


graphwalker-restful

G raph Walker RESTFUL 模式


graphwalker-websocket

G raph Walker Websocket 模式





长按指纹识别图中的二维码,获取更多测试干货分享!







将我们公众号置顶 不会漏掉我们的原创干货哦!




分享给朋友:
您可能感兴趣的文章:
随机阅读: