Tutorials 20 April 2020

使用Postman进行负载测试API

Mostafa Moradian(开发者推广大使)著,Ng Wai Foong 译
Chinese

📖你将会学到什么呢

  • 如何将Postman集合转换为k6脚本?
  • 如何在k6中运行由转换器创建的脚本?

引言

在本文中,我将解释如何创建Postman集合,以及使用Postman集合来负载测试我们的测试API。整个过程非常简单,您需要导出Postman集合,使用我们的postman-to-k6转换器将其转换为脚本,并使用生成后的k6脚本来负载测试API,如下所示:

快速入门指南

# convert postman collection to k6 test
$ postman-to-k6 test-api.json \
-e env.json \
-o k6-script.js
# run load test
$ k6 run \
--vus 100 \
--duration 5m \
k6-script.js

深入指南

测试API及其测试场景

为了演示k6在不同情况下的功能,我们创建了具有各种示例端点的测试API,在test-api.k6.io链接上,这些端点在Postman集合中可用:

公开API

  • 列出所有公共crocodile(API中的示例参数)
  • 取得一个公共crocodile

注册和认证API

  • 注册新用户
  • Bearer或JWT令牌认证

私有API

  • 列出所有crocodile
  • 取得一个crocodile
  • 新建新crocodile(最多100个)
  • 更新您的crocodile
  • 更新crocodile中的选定字段
  • 删除您的crocodile

本文的用例是测试所有公开和私有API,对于私有API,您可以创建一个用户并提取其令牌,提取后的令牌用于进行其他API调用,调用私有API时,顺序是非常重要的,因为您不能删除不存在的资源。顺便说一下,API中的实例参数(crocodile)也是我们的吉祥物。

测试API,Postman集合

为了简化我们的测试,并演示我们的Postman到k6转换器的用法,我创建了一个Postman集合,其中包含了几乎所有测试API的请求,您将很快了解如何使用此Postman集合。

测试Postman集合API

这个集合包含一组集合变量、环境变量、预脚本、测试、授权两种不同的机制,以及Postman沙箱API的用法。

使用Postman集合对我们的测试API进行负载测试

我们为您创建了一个Postman集合转换为k6脚本的工具,它叫postman-to-k6,您可以在发布版本通知中阅读更多关于其功能的信息。

为了将您的Postman集合转换成k6脚本,您应该采取以下步骤:

(可选)步骤1:克隆版本库并跳到第五步骤

我为这篇文章创建了一个存储库,其中包含导出后的Postman集合,转换后的脚本和其他相关的文件。您可以克隆存储库并将test-api.jsonenv.json文件导入到Postman应用程序中。

这个存储库包含了我们负载测试API所需要的一切内容,因此您可以跳到第五步骤,当使用您自己的集合时,您应该遵循所有的步骤,以便能够从Postman集合中转换为k6脚本,并且能够使用它来运行负载测试。

$ git clone https://github.com/k6io/example-postman-collection.git

步骤2:安装Node.js(如果尚未安装)

我强烈建议您使用nvm,这是一个Node.js版本管理器,可以在您的机器上同时启用多个Node.js版本,且能够快速切换到其中任何一个版本。

步骤3:安装postman-to-k6工具

这个postman-to-k6工具是为了帮助您将Postman集合中的请求转换为k6脚本开发的,k6脚本实际上是JavaScript代码。

$ npm install -g postman-to-k6

步骤4:将导出的Postman集合转换为k6脚本

假设您导出的集名为test-api.json,您可以运行此命令将其转换为k6脚本,输出的env.json文件包含了从Postman导出的所有环境变量。

$ postman-to-k6 test-api.json -e env.json -o k6-script.js

如果您需要对测试进行更多的微调(就像我们上面所做的那样),比如在您的代码中添加数据或更改环境变量,只需查看postman-to-k6 README选项部分。

转换器转换后的脚本应如下所示,我已手动将测试运行的持续时间添加为1分钟,我还添加了虚拟用户(Virtual Users)数,这两个选项让脚本在100个虚拟用户的情况下运行一分钟,这100个用户会尽可能多地发出请求来测试服务器,您会在下一张截图中看到该请求。

1import "./libs/shim/core.js";
2import "./libs/shim/urijs.js";
3import URI from "./libs/urijs.js";
4import {
5 group
6} from "k6";
7
8export let options = {
9 maxRedirects: 4,
10 duration: "1m",
11 vus: 100
12};
13
14const Request = Symbol.for("request");
15postman[Symbol.for("initial")]({
16 options,
17 collection: {
18 BASE_URL: "https://test-api.k6.io/"
19 },
20 environment: {
21 USERNAME: "test@example.com",
22 PASSWORD: "superCroc2020",
23 FIRSTNAME: "John",
24 LASTNAME: "Doe",
25 EMAIL: "test@example.com",
26 ACCESS: null,
27 REFRESH: null,
28 CROCID: null
29 }
30});
31
32export default function () {
33 group("Public APIs", function () {
34 postman[Request]({
35 name: "List all public crocodiles",
36 id: "3ddd46c4-1618-4883-82ff-1b1e3a5f1091",
37 method: "GET",
38 address: "{{BASE_URL}}/public/crocodiles/"
39 });
40
41 postman[Request]({
42 name: "Get a single public crocodile",
43 id: "9625f17a-b739-4f91-af99-fba1d898953b",
44 method: "GET",
45 address: "{{BASE_URL}}/public/crocodiles/1/"
46 });
47 });
48
49 // NOTE: The rest of the requests can be accessed
50 // from the repository in step 1
51});

生成的脚本与普通的k6脚本略有不同,因为它包含了各种抽象来支持Postman中的功能,所以您可以将它们与k6的常规http requests函数混合使用。此外,脚本旁边还有一个libs目录,其中包含Postman脚本正常运行所需的垫片和库。

步骤5:安装k6

k6支持各种平台,包括Windows、Linux、macOS和Docker,按照安装说明为您的系统安装k6。

注意:您也可以使用choco k6 package在Windows上进行安装。

步骤6:使用生成后的脚本运行k6

将集合转换为k6脚本后,您可以按以下方式运行k6:

$ k6 run k6-script.js

脚本的结果显示在以下命令行界面输出中:

/\ |‾‾| /‾‾/ /‾/
/\ / \ | |_/ / / /
/ \/ \ | | / ‾‾\
/ \ | |\ \ | (_) |
/ __________ \ |__| \__\ \___/ .io
execution: local
output: -
script: k6-script.js
duration: 1m0s, iterations: -
vus: 100, max: 100
done [==========================================================] 1m0s / 1m0s
█ Public APIs
█ Registration and authentication
█ Private APIs
data_received..............: 8.8 MB 146 kB/s
data_sent..................: 4.8 MB 80 kB/s
group_duration.............: avg=753.07ms min=239.15ms med=495ms max=4.06s p(90)=1.37s p(95)=1.73s
http_req_blocked...........: avg=12.31ms min=362ns med=1.52µs max=3.47s p(90)=1.83µs p(95)=1.96µs
http_req_connecting........: avg=1.95ms min=0s med=0s max=779.59ms p(90)=0s p(95)=0s
http_req_duration..........: avg=211.11ms min=104.42ms med=183.12ms max=924.43ms p(90)=304.25ms p(95)=404.24ms
http_req_receiving.........: avg=1ms min=41.14µs med=169.38µs max=130.94ms p(90)=328.31µs p(95)=2.22ms
http_req_sending...........: avg=205.91µs min=38.06µs med=163.76µs max=113.06ms p(90)=258.45µs p(95)=302.86µs
http_req_tls_handshaking...: avg=8.69ms min=0s med=0s max=2.43s p(90)=0s p(95)=0s
http_req_waiting...........: avg=209.9ms min=104.05ms med=182.22ms max=891.77ms p(90)=301.29ms p(95)=402.41ms
http_reqs..................: 26363 439.382653/s
iteration_duration.........: avg=2.28s min=1.43s med=2.01s max=6.55s p(90)=2.86s p(95)=3.64s
iterations.................: 2588 43.133267/s
vus........................: 100 min=100 max=100
vus_max....................: 100 min=100 max=100

关于使用postman-to-k6转换器的说明

1. 我们是否应该基于postman-to-k6转换器和Postman集合进行负载测试?

如果您使用转换器作为入门方式,答案是不应该,如果您打算连续转换Postman集合,并且此后无需进行大量手动修改,那么答案是应该。我们建议您使用转换器作为一种简单的方式来加载,然后将您的脚本重写为惯用的 k6 代码,因为我们相信它更易于维护,并且随着时间的推移不太可能降低性能。但是,如果您不断地从Postman集合转换,并按原样运行脚本输出,那么保持原样可能是有意义的。

2. 我可以直接使用转换后的脚本中的所有功能吗?

不可以,由于k6是使用Goja来运行JavaScript,而且它与浏览器和Node.js API是不兼容,因此有一些功能是无法运行使用的。但是您可以通过导入JavaScript模块来解决这个问题,关于兼容库的列表,请参考jslib.k6.io

3. 对剧本做了哪些调整才能使其正常运行?

首先,我删除了包含pm.sendRequest的预请求脚本,因为转换器并不支持这个,所以我将jsonData.hasOwnProperty替换为response.json("selector"),即用于提取JSON响应信息

测试Postman集合API预请求脚本

Postman API与k6 API

以下是Postman APIk6 API的对比,该表还包含Postman GUI应用程序中的功能,由于k6从一开始就可以编写脚本,您可以选择用JavaScript编写逻辑。此外,Postman是支持使用Javascript来执行各种任务,但Postman的核心在于通过丰富的GUI元素来操作。

功能Postman APIk6 API
导入外部库一些选定的库一些选定的库加上捆绑库
(非浏览器,非Node.js API)
发出请求
处理响应
参数化
REST
GraphQL
小甜饼(Cookies)
网络代理
SSL
OpenAPI/Swagger
(直接导入)

(通过openapi-generator中的k6生成器)
断言
(断言)

(Checks API)

(集合)

(Group API)
解析HTML
(需要外部库)

(通过内部HTML API)
上传文件
测试生命周期
(需要脚本)

(内置功能 )

根据以上的表,这两个API都支持许多功能,各有千秋,有些功能需要外部库,而有些则是内置功能,这两个API都可以用JavaScript编写脚本,但两者均不支持所有功能,因为两库中使用了各种浏览器和Node.js API。

然而,有些功能只有在k6上才可用,原因在于Postman是专注于API测试或API功能测试服务的,而k6更专注于API负载测试

功能测试与负载测试

功能测试主要是通过API向系统提供输入(作为黑箱),并检查结果,而负载测试基本上与功能测试执行相同的功能,但在系统的输入上有额外的负载

功能测试在每个端点上提供输入,并根据一组规范对返回的结果进行正确性验证。反过来说,负载测试会在每个端点上提供大量负载,并将汇总所有响应返回的元数据。

用于衡量性能的负载测试指标

元数据将包括发送请求和返回响应所需的时间来衡量性能,以便根据各种指标衡量业绩。例如,您可以测量所有请求的HTTP请求持续时间,并获取其最小值、最大值、平均值、中位数、第90和第95百分位数。

使用阈值断言测试是否通过还是失败

您可以设置某个阈值来断言测试是否通过还是失败。例如,您可以指定希望平均响应时间小于500毫秒,如果平均值低于该数值,则测试将失败,概念和软件测试中的断言是一样的。

使用标签过滤结果

由于许多测试涉及来自不同端点的不同结果,如果能对结果进行过滤,就会容易很多,k6支持标签来满足此需求。

负载测试WebSocket服务器

在协议实现方面,与Postman相比,WebSocket是k6中可用的功能之一,您可以使用k6中的内置功能对您的WebSocket服务器进行负载测试。

结论

在本文中,我介绍了Postman,postman-to-k6转换器和我们的k6负载测试工具,您可以使用这些工具将Postman中的API请求转换为k6脚本,以对您的API进行负载测试。我们的postman-to-k6工具支持许多Postman功能。

我们的最终目标是简化使用我们负载测试工具k6的过程,我们创建了许多集成教程,可以帮助您开始在您的基础设施中进行负载测试。

< Back to all posts