自动化工具 [腾讯 TMQ] 基于模型的自动化测试工具——GraphWalker

匿名 · 2017年01月19日 · 1787 次阅读

一、概述
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. 覆盖准则(路径生成准则)

状态覆盖

转换覆盖

  1. 行走算法

随机行走

覆盖引导

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;

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

示例:

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

让我们从 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,但在不同模型间跳转时。ModelA 中的 eB,与 ModelB 中的 eB 是不同变量。

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

多模型之间跳转,相当与 GraphWalker 自动在 SHARD 状态之间。建立 2 条虚拟边,GraphWalker 将根据算法选择是否前往 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。

  1. 构建模型(使其不可变),并将其提供给 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 "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

  1. 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 工具核心

Algorithm:

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

Condition:

路径遍历结束条件

Event:

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

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

Generator:

根据调用算法生成路径。

Machine:

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

Modle:

模型类

graphwalker-dsl

yed 文件解释器,用户解析.graphml 文件

graphwalker-io

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

graphwalker-java

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

graphwalker-plugin

为 GraphWalker 作为 mavenplugin 提供支持。

graphwalker-restful

GraphWalker RESTFUL 模式

graphwalker-websocket

GraphWalker Websocket 模式

【TMQ 新书专栏】https://weidian.com/?userid=984448577

原文链接:http://tmq.qq.com/2016/12/graphwalker/

关注我们的微信公众号查看完整内容哦~~~~

想知道更多测试相关干货
请关注我们的微信公众号:腾讯移动品质中心 TMQ
二维码:
这里写图片描述

版权声明:腾讯 TMQ 拥有内容的全部版权,任何人或单位对本贴内容进行复制、转载时请申明原创腾讯 tmq,否则将追究法律责任。

暂无回复。
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册