演练:创建并运行API自动化测试项目
本项目的完整代码可以在样例
api_service
中找到。在“帮助”菜单的“样例”中可以找到所有样例。
在这个演练中,借助npm库——json-server
搭建一个简单的数据服务后台,用于响应get、post等请求,完成数据的增删改查(CRUD),从而完成RESTful API自动化测试的演练。
在本演练中,我们将:
- 创建BDD场景并实现场景代码
- 引入开源Node库
json-server
模拟API服务器 - 运行自动脚本并查看测试报告
- 将脚本变为数据驱动的测试
我们计划模拟和测试项目中五种HTTP请求类型:get
、post
、put
、patch
和delete
。每一种请求类型都由一个场景大纲来管理测试,从而可以通过添加数据行来快速增加测试用例。
下面是操作步骤。
1. 新建项目
- 点击【新建项目】按钮,弹出创建项目对话框。
- 【项目名】中输入“APITesting”,【项目模板】选择【API Sevice】,【项目路径】选择桌面或某个其它路径。
- 点击【创建】按钮,即可完成创建。
2. 运行环境配置
基于node.js的项目通常需要用到一些NPM依赖包。这个API自动化测试项目中用的第三方依赖包有:
json-server
包:用于从文件启动数据服务;killport
包:用于停止目标端口的服务;
而用于发起HTTP请求的got
库由CukeTest内置了,因此不需要重新安装,有关内置API自动化库的说明,可以参考API自动化库-got。当然如果希望使用其它的库,比如axios
也可以一并安装,但脚本需要改动,这里就不展开了。
这些安装包已经由项目模板配置在package.json中。请按照NPM包的下载和更新提示的步骤安装上述依赖包。安装完毕后就可以启动数据服务以便进行脚本测试。
打开命令行浏览到项目目录中,执行以下命令完成安装:
npm install
注意:您应该安装Node.js以使用npm命令。转到node.js网站以了解更多详细信息。
启动数据服务
点击工具栏中的启动命令行终端按钮打开命令行,使用以下命令:
- Windows系统
node_modules\.bin\json-server.cmd data.json --watch
- Linux系统
node_modules/.bin/json-server data.json --watch
启动服务,上面的命令分为三个部分:
json-server
包提供的命令行工具路径;- 用于数据服务的
json
文件; - 其它选项。
当然也可以执行打包好的命令:
npm run json-server
这条命令可以在项目的
package.json
文件第8行找到。
3. 编写测试脚本
分为编写feature文件和实现自动化脚本两部分。
feature文件 在项目目录下新建一个feature文件,编辑用例描述。
# language: zh-CN 功能: API Testing 练习 更改用户名字 场景: 更改用户的名字 当发送put请求到"http://127.0.0.1:3000/users/1",请求数据为 """ { "name":"Susan" } """ 那么发送get请求到"http://127.0.0.1:3000/users/1",用户名应该为"Susan"
第一个步骤中借助文本字符串传入了一个字符串,之后在脚本中会将其解析为对象并写入到数据服务中。
- 您可以删除默认剧本文件“feature1.feature”以及脚本文件“definition1.js”中的相应步骤定义。
- 在“api_testing.feature”上,单击每个步骤右侧的每个灰色按钮,为它们生成代码存根。代码在“definition1.js”文件中生成。请注意,生成步骤定义存根时,灰色按钮变为橙色。
点击操作步骤后的灰色按钮,生成自动化代码样例。
进一步实现这些存根代码,实现后的definition1.js自动化代码如下:
JavaScriptconst { Given, When, Then } = require('cucumber'); const got = require('got'); const assert = require('assert'); When("发送put请求到{string},请求数据为", async function (url, docString) { let putdata = { headers: { 'Content-Type': 'application/json' }, json: true, body: JSON.parse(docString) }; await got.put(url,putdata); }); Then("发送get请求到{string},用户名应该为{string}", async function (url, name) { let res = await got.get(url) res = JSON.parse(res.body) return assert.equal(res.name,name); });
这个代码很容易读懂,在“发送put ...”步骤中,它构造JSON请求,并使用
PUT
方法将请求发送到URL,在“发送get ...”步骤中,使用GET
方法获取JSON 对象数据,然后验证其中的姓名与我们在上一步中设置的姓名相同。你可以注意到,一旦代码实现了,步骤文本旁边的按钮变成了绿色。
如果通过将文章中的部分代码复制到编辑器来实现代码,请确保变量名称与默认生成的框架函数匹配,例如,生成的默认参数为“arg1”,“arg2”等,请将其更新为与之匹配内容。
4. 步骤和步骤定义的关联
可以用以下步骤在剧本文件中的步骤和代码之间互相跳转:
点击feature 文件中操作步骤后面的【绿色按钮】 ,可以跳转到对应的自动化代码实现。
在js文件中步骤定义部分,右键—选择【定位步骤描述】 即可定位到测试用例部分。
5. 运行项目
运行API自动化脚本,需有被测的API,借助json-server
包,我们可以启动一个简单的数据服务,如启动数据服务一节所示。
在CukeTest界面中,点击【运行项目】 按钮,即可运行自动化脚本,运行完成后自动生成测试报告。
6. 测试报告操作
在测试报告浏览界面,通过工具条上的按钮可以执行对测试报告的系列操作。例如将测试报告导出到pdf,也可以将测试报告以邮件方式发送出去。下面是工具条上面的操作:
点击【保存】按钮 ,弹出对话框,填写【文件名称】,点击保存,即可保存为pdf文件。
点击【打开文件夹】按钮 ,可以打开测试报告所在文件夹。
点击【在浏览器中显示】 ,会在默认浏览器中打开报告。
- 点击【html报告主题】 ,可以选择不同的报告主题。
- 点击【电子邮件】 ,会默认打开Outlook客户端并将测试报告作为附件。
- 点击【展开】 ,会展开报告中的所有场景。
- 点击【折叠】 ,会折叠报告中的所有场景。
7. 将测试脚本改为数据驱动
许多API测试需要将不同的测试参数传递给API,以验证它是否适用于所有这些参数。为了使这个测试成为数据驱动,我们可以先将它转换为Scenario Outline。以下是步骤:
右键单击方案标题,选择“更改场景类型”=>“方案大纲”:
它会将您的场景转换为场景大纲,并将参数提取到示例表中:
我们现在更新Scenario Outline和示例表以获得正确的参数名称和数据:
a. 在步骤文本和表格标题中将“param1”更改为“url”。
b. 在步骤文本和表头中将“param2”更改为“first_name”。您还应该将DocString中的“Susan”替换为“\
”。自动转换不会替换您的DocString内容,因此您需要自己完成。 c. 将更多数据行添加到示例表中。您可以双击表格主体,按Tab键直到导航到新行,然后填充一些新数据,使其与第一行数据类似,只更改id和名称部分。编辑完成后,整个场景如下:
再次运行测试项目后,您将看到该报告现在包含3个场景。对于示例中的每一行,它将在填充行数据的情况下运行场景大纲一次。这是Cucumber的功能特点。您可以在报告中看到前两个场景成功,而第三个场景失败。
打开项目文件夹中的“data.json”文件,您还可以看到前2个json记录的名称已更新为“Susan”和“Jason”。所以我们发现了问题,因为数据服务只有2条记录,当我们尝试更新第3条记录时,数据服务返回错误“未找到”。为了使测试通过,您需要添加更多记录。因此,将以下数据复制到data.json文件中的“users”数组中并保存:
{ "id": 3 }, { "id": 4 }
注意:您需要重新启动到数据服务才能使更改生效。```
然后再次运行测试,您应该在报告中看到所有三个方案都已通过。再次打开“data.json”文件,注意第三个json对象也已被自动化脚本更新为名称“John”。
8. 添加环境准备/清理操作
在自动化测试中,为了保证测试运行的一致性,会要求在测试结束后进行数据恢复或清理,以供下一次测试运行使用。
同样的,在测试开始前我们也可以写入测试运行的准备操作,比如此项目中的启动数据服务操作,并且在运行结束后结束数据服务,避免端口占用。
这些操作都可以使用CukeTest提供的钩子函数Hooks来实现。
在钩子函数中添加以下操作:
项目执行前:
- 用原始数据文件
data_origin.json
文件覆盖data.json
文件,从而保持每次执行采用的是相同的数据。 - 启动数据服务,启动后数据服务会开始监听
3000
端口的请求。
项目执行后:
- 停止
3000
端口正在运行的数据服务。 - 短暂延时,等待命令行窗口关闭。
在项目的support
目录中新建hook.js
,之后可以将钩子函数相关的函数都丢到这里面。
const { Util } = require('leanpro.common');
const { AfterAll,BeforeAll } = require('cucumber');
const {readFileSync, writeFileSync} = require('fs');
const {join} = require('path');
const {spawn} = require('child_process');
const kill = require('kill-port');
const root = join(__dirname, '../../');
let subprocess;
BeforeAll(async function () {
// 还原data.json文件
let text = readFileSync(join(root, 'data_origin.json'),
{encoding: "utf-8"});
writeFileSync(join(root,'data.json'), text);
// 启动数据服务
let subprocess = spawn(join(root, 'node_modules\\.bin\\json-server.cmd'),
['data.json'],
{ detached: true,shell:false })
})
AfterAll(async function () {
kill('3000'); // 根据端口停止数据服务
await Util.delay(1000);
})
总结
在本演练中,我们模拟了一个管理用户的RESTful API服务,使用BDD测试脚本测试此服务,更改用户名,然后验证名称是否已实际修改。同时我们将这个场景转换成了数据驱动的场景大纲,并用多组不同的数据测试了这个场景。