首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【腾讯TMQ】基于模型的自动化测试工具:GraphWalker

【腾讯TMQ】基于模型的自动化测试工具:GraphWalker

原创
作者头像
腾讯移动品质中心TMQ
修改2017-06-30 16:59:47
7.2K1
修改2017-06-30 16:59:47
举报

作者:陆瑶瑶

一、概述

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 to explain the failure

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模式

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、概述
  • 二、背景知识
    • 2.1 模型(Model)
      • 2.2 测试需求选择
        • 2.3 测试用例生成
          • 2.4 测试具体化
            • 2.5 执行测试
            • 三、GraphWalker能做什么
            • 四、通过GraphWalker建模
              • 4.1 顶点(Vertex)
                • 4.2 边(Edge)
                  • 4.3 建模规则
                  • 五、路径生成器和结束条件
                    • 5.1 路径生成器
                      • 5.2 结束条件
                      • 六、GraphWalker工作方式
                        • 6.1 GraphWalker提供3种工作方式
                          • 6.2 作为java第三方库
                            • 6.3 以offline模式,加载model
                              • 6.4 以online模式,作为service
                              • 七、GraphWalker命令行
                                • 7.1 Global options
                                  • 7.2 Offline
                                    • 7.3 Online
                                    • 八、Restful或WebSocket服务的区别
                                      • 8.1 Restful
                                        • 8.2 Web Socket
                                        • 九、Web Socket API接口
                                          • 9.1 start
                                            • 9.2 hasNext
                                              • 9.3 getNext
                                                • 9.4 getData
                                                  • 9.5 visitedElement
                                                  • 十、REST API接口
                                                    • 10.1 load
                                                      • 10.2 hasNext
                                                        • 10.3 getNext
                                                          • 10.4 getData
                                                            • 10.5 setData
                                                              • 10.6 restart
                                                                • 10.7 fail
                                                                  • 10.8 getStatistics
                                                                  • 十一、GraphWalker源码及构建
                                                                    • 11.1 编译GraphWalker前准备工作
                                                                      • 11.2 获取源码
                                                                        • 11.3 Build GraphWalker jar包
                                                                          • 11.4 GraphWalker 工程结构
                                                                          领券
                                                                          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档