极狐GitLab自动化测试指南03——性能测试

1 理论篇

1.1 什么是性能测试

WIKI百科对于性能测试的解释是:

性能测试用于评估和确定系统在特定工作量下的响应和稳定方面的性能。可以用于调查、测量、验证系统的其他质量属性,例如可扩展性,可靠性和资源使用情况。

性能测试按照测试目的不同,可分成不同类型,常见的类型有:

  • 负载测试:负载测试是最简单的性能测试形式。通常用来了解系统在预期负载下的行为。如测试系统是否可以承受预期的并发用户数,以及重要业务的响应时间等。在测试期间还监视了数据库、服务器等,有助于识别系统中的性能瓶颈。通俗的讲就是“这样的压力你能不能承受”。
  • 压力测试:压力测试通常用于了解系统性能的上限。与负载测试不同,压力测试通过不断增加负载,目的是找出系统性能的下降点。也可以用来确定如果系统负载远高于预期的最大值,系统性能是否表现足够。通俗的讲就是“你究竟能承受多少压力”。
  • 浸泡测试:也被称为耐力测试、长跑测试。目的是确定系统是否可以维持连续的预期负载。如在浸泡测试期间,监视内存利用率以检测是否存在内存泄露。也可以用来确认系统在长期持续活动后的吞吐量和响应时间是否有下降。通俗的讲就是“这样的压力你能不能一直承受”。
  • 冲击测试:也被称为尖峰测试。通过突然增加或减少大量用户产生的负载并观察系统行为进行测试,目的是确定系统性能是否会受到影响,以及它能否处理负载的急剧变化。通俗的讲就是“这样的压力突然来一下你能不能承受”。

1.2 为什么要做性能测试

性能测试是一种非功能软件测试技术,是确保软件质量的关键。但大多数情况下,它被视为单独的事后步骤,并且在功能测试完成之后才进行,甚至在代码发布之后才进行。

企业一般出于以下原因之一运行性能测试:

  • 确定系统是否满足性能要求
  • 定位系统中的性能瓶颈
  • 测量系统的哪些部分或工作负载导致系统执行不良
  • 比较两个或以上的系统并确定其中性能最好的一个

性能测试的目的包括评估应用系统吞吐量、处理速度、数据传输速度、网络带宽使用、最大并发用户、内存利用率、工作负载效率和命令响应时间等。

某种意义上讲,性能测试不像接口测试、单元测试那么“刚需”。但当企业有上面提到的这些性能测试的需求,或者将系统性能也作为产品本身的重要评估指标,那就需要开展性能测试。性能测试的门槛相对较低,一般是基于接口测试编排。如上一篇文章《极狐GitLab自动化测试指南02——接口测试》中提到的Postman、Apifox也可以进行性能测试。所以我将性能测试作为该系列文章的第三篇,跟随接口测试,趁热打铁。

1.3 如何做性能测试

从流程层面来说,微软在《Performance Testing Guidance for Web Applications》中列出了Web应用性能测试的7个核心活动:

  1. 确定测试环境和工具:确定可供使用的生产环境、测试环境和测试工具。 在测试和生产环境中记录硬件、软件、基础设施规范和配置,以确保一致性。
  2. 确认可接受的性能标准:确定性能测试的指标。一般来说,用户比较关注系统响应时间,业务比较关注系统吞吐量,运维比较关注资源使用情况。
  3. 计划和设计测试:确定关键场景,定义测试数据以及确定如何模拟数据的多样性。
  4. 准备测试环境和工具:在执行测试之前配置测试环境并准备好测试工具。
  5. 实现测试:根据测试计划编写性能测试脚本。
  6. 执行测试:执行测试,收集并监控测试结果。
  7. 分析结果、优化和重新测试:整理和分析测试结果。与团队分享结果发现,通过解决发现的性能缺陷来优化应用程序。 重复测试,以确认每个问题都已被彻底解决。

从工具层面来说,性能测试工具主要分为两个类别,目前市面上大多数性能测试工具已经是这两类工具的集合体:

  • 脚本工具:通过录制或者编写脚本模拟关键业务流程。
  • 监控工具:观察正在测试的应用系统的行为和响应特征。

从实践层面来说,有以下几个注意事项:

  • 性能测试环境应与其他环境(如UAT或开发环境)隔离。
  • 创建尽可能接近生产环境的性能测试环境。
  • 多次运行性能测试以获得更准确的测试结果。
  • 不要在两次测试之间更改性能测试环境。
  • 性能缺陷越早发现越好补救。

2 实践篇

2.1 极狐GitLab Browser Performance

浏览器性能测试是极狐GitLab专业版提供的功能,主要是用于测试Web系统的性能,比如页面加载速度,渲染时间等。可以帮助测试人员找出哪些页面、JS、图片素材加载缓慢,这些问题都会直接影响访问者的用户体验。

极狐GitLab的浏览器性能测试是基于集成了sitespeed.io这款网站性能测试工具做了封装,无需编写测试脚本,所以在使用方面非常简单。

2.1.1 准备Runner环境

运行极狐GitLab Browser Performance,需要Docker或者Kubernetes的GitLab Runner,详见:GitLab Runner Executors | GitLab

此外还需进行设置,让Runner支持Docker-in-Docker,详见:Use Docker-in-Docker

2.1.2 创建测试项目

浏览器性能测试可根据实际情况参考以下两种方式进行创建和管理:

  1. 独立管理

    测试和开发项目分开管理,一般是由测试人员为浏览器性能测试创建一个独立的代码仓,这种方式适合在有需要的时候对指定的网站进行浏览器性能测试。.gitlab-ci.yaml内容如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # docker-in-docker
    image: docker:19.03.13
    variables:
    DOCKER_HOST: tcp://docker:2375
    DOCKER_TLS_CERTDIR: ""
    services:
    - docker:19.03.13-dind
    # 引用浏览器性能测试模板
    include:
    template: Verify/Browser-Performance.gitlab-ci.yml
    # 设置浏览器性能测试url
    browser_performance:
    variables:
    URL: https://xx.xx.com
  2. 统一管理

    测试和开发项目统一管理,一般是由开发人员在当前项目的CI/CD设置中加上浏览器性能测试,可以使用极狐GitLab的环境变量结合rules来控制测试的执行策略。.gitlab-ci.yaml内容如下:

    1
    2
    3
    4
    5
    6
    browser_performance:
    # PERFORMANCE_TEST变量不为空则执行浏览器性能测试任务
    rules:
    - if: $PERFORMANCE_TEST != null
    variables:
    URL: https://xx.xx.com

    这样就可以实现平时正常的构建不触发浏览器性能测试任务,当需要执行测试任务时,手动触发流水线任务,给PERFORMANCE_TEST环境变量设置一个值,就可以只在这次构建中执行测试任务。

2.1.3 自动执行测试

成功运行流水线后,可下载作业(Job)的制品(Artifacts),或配合极狐GitLab Pages功能,以HTML格式查看测试报告:

此外可以在合并请求(Merge Requests)页面展示源分支和目标分支的浏览器性能测试对比报告,这个功能有助于代码评审人员对代码进行综合评估。

值得一提的是这个对比报告基于一个固定格式的JSON文件,只需要在CI/CD中将这个格式的文件以制品(Artifacts)进行上传,就可以在MR中展示这个对比报告。如果有对极狐GitLab CI/CD功能比较熟悉的读者,相信已经知道可以利用这个功能实现和其他浏览器性能测试工具的集成。

2.2 极狐GitLab Load Performance

极狐GitLab专业版也集成了Grafana Lab的性能测试工具K6,K6使用Golang开发,使用JS作为脚本语言,支持冒烟测试、负载测试、压力测试、长跑测试,是一款比较轻量的性能测试工具。但是它没有JMeter那种GUI,对于没有编码基础的测试人员,上手稍微有点难度,不过好在官方文档丰富,走得是简洁的Geek风。

2.2.1 下载安装K6

使用集成了K6的极狐GitLab Load Performance功能,同样需要Docker或者Kubernetes的GitLab Runner,也需要支持Docker-in-Docker,这部分内容可以参考Browser Performance章节的内容。

基于K6做性能测试,还是需要在本地进行测试脚本的编写和调试,关于K6的安装可以参考K6的官方文档,这里以Docker为例:

1
docker pull grafana/k6

拉取官方最新的镜像,就可以进行脚本编写了。

2.2.2 编写测试脚本

沿用上一篇文章《极狐GitLab自动化测试指南02——接口测试》的示例,假如我们要对“唱片管理系统”进行负载测试。目的是测试“发布唱片”这个功能在1000个用户,总共10000次请求下的性能情况。那么参考脚本script.js如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import http from 'k6/http';
import { check } from 'k6';
import exec from 'k6/execution';

export default function () {
// exec.scenario.iterationInTest 是测试中的唯一ID
var index = exec.scenario.iterationInTest
// 待测试API
const url = 'http://wurang.net:9080/albums';
// 生成测试数据
const payload = JSON.stringify({
"id": index,
"title": "标题" + index,
"artist": "艺术家" + index,
"price": 10 + index,
});
const params = {
headers: {
'Content-Type': 'application/json',
},
};
// 请求API
const res = http.post(url, payload, params);
// 断言:状态码应为201
check(res, {
'is status 201': (r) => r.status === 201,
});
// 断言:返回唱片的id应与创建唱片的id一致
check(res, {
'verify id': (r) =>
r.json()["id"] == index,
});
}

大致内容有3部分:

  • 生成测试数据:示例是利用固定前缀加唯一ID生成了唱片信息。实际操作中也可以结合一些随机数或者制作专门的测试数据集,放在Excel中,然后使用K6加载测试数据集。
  • 请求API:通过测试数据请求待测试的API。示例中只是对一个接口进行了测试,实际操作中可以按照业务流程顺序请求相关接口,作为一个测试场景。
  • 断言:示例中通过判断返回状态码和返回JSON数据的ID是否与测试数据的ID一致来验证接口请求是否正确。

脚本编写完成后,可以在本地进行调试,这里以Docker下的K6为例:

1
docker run -it -v ~/workspace/performance-test-k6:/test -w /test grafana/k6 run --vus 1000 --iterations 10000 script.js

通过vus参数设置虚拟用户,通过iterations参数设置请求次数,运行测试,观察结果是否正确。

2.2.3 自动执行测试

最后测试脚本可以参考Browser Performance章节“创建测试项目”部分选择不同的方式放在极狐GitLab代码仓上进行管理。在极狐GitLab CI/CD中使用K6的.gitlab-ci.yaml内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# docker-in-docker
image: docker:19.03.13
variables:
DOCKER_HOST: tcp://docker:2375
DOCKER_TLS_CERTDIR: ""
services:
- docker:19.03.13-dind

# 引用K6性能测试模板
include:
template: Verify/Load-Performance-Testing.gitlab-ci.yml

load_performance:
variables:
# 测试脚本路径
K6_TEST_FILE: script.js
# GitLab 默认的K6_VERSION是0.27.0,可以指定版本号
K6_VERSION: 0.37.0
# 测试参数,对应本地调试命令中的vus和iterations
K6_OPTIONS: '--vus 1000 --iterations 10000'

与浏览器性能测试一样,可以在合并请求(Merge Requests)页面展示源分支和目标分支的负载性能测试对比报告。

2.3 极狐GitLab集成JMeter

性能测试最“出名”的两款工具是LoadRunner和JMeter,其中JMeter是Apache组织基于Java开发的性能测试工具,而且是开源免费工具,在国内开发者中使用的比例最高。JMeter除了有GUI便于测试人员上手外,功能也非常强大,网络上相关的教程、实践文章也比较多,这里仅展示JMeter的基础功能并实现和极狐GitLab的集成。

2.3.1 下载安装JMeter

JMeter的下载地址可在官网上找到,因为JMeter是基于Java 8开发,所以需要JDK/JRE环境。下载解压后,打开bin\jmeter即可看到软件界面。

2.3.2 编写测试脚本

与上文的示例场景一样,同样基于“唱片管理系统”进行负载测试。需要按照以下步骤完成JMeter的测试脚本编写:

  1. 修改测试计划名称,如“图书管理系统负载测试”。

  2. 右键测试计划,“添加——线程(用户)——tearDown线程组”,线程数为1000,即代表1000个用户,循环次数为10,即代表每个用户循环执行10次,共计执行10000次。类似K6的vusiterations参数。

  3. 右键线程组,“添加——配置元件——计数器”,内容如下,用于作为测试数据的唯一ID。其中Starting Value是起始值,这里从4开始。引用名称是这个计数器作为环境变量使用的名称,使用环境变量的格式是${引用名称}

  4. 右键线程组,“添加——取样器——HTTP请求”,填写名称协议服务器名称或IP端口号HTTP请求路径内容编码消息体数据,用于访问待测试的API。其中消息体数据用到了上一步创建的计数器,并且使用了${__intSum}这个JMeter的内置函数,实现了两数相加。

  5. 右键线程组,“添加——断言——响应断言/JSON断言”,下图展示的是JSON断言,填写Assert JSON Path exists Expected Value实现两者的对比。

  6. 右键线程组,“添加——监听器——察看结果树/聚合报告”,用于查看测试结果。

  7. 菜单栏“运行——启动”,开启性能测试,在聚合报告页面可以查看测试结果。需要说明的是在实际操作中,不建议在GUI下直接开启测试,这样会导致JMeter程序卡顿甚至卡死,官方建议在GUI模式下编写脚本和调试,在非GUI模式下进行测试。

  8. 菜单栏“工具——Generate HTML Report”可以导出HTML的测试报告。

  9. 测试计划保存为test.jmx

  10. 在非GUI模式下进行测试,并导出HTML报告,可使用以下命令:

    1
    jmeter -n -t test.jmx -l result.jtl -e -o ./report

​ 其中-n为非GUI模式,-l为测试结果路径, -e为生成HTML报告,-o为导出HTML报告的路径。

2.3.3 自动执行测试

同样可以把JMeter的测试计划test.jmx放在极狐GitLab代码仓上进行管理。在极狐GitLab CI/CD中使用JMeter的.gitlab-ci.yaml内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
stages:         
- test
performance-test-job:
stage: test
image: justb4/jmeter
# 非GUI执行测试任务
script:
- jmeter -n -t test.jmx -l result.jtl -e -o ./report
# HTML报告上传制品
artifacts:
paths:
- report

成功运行流水线后,可下载作业(Job)的制品(Artifacts),或配合极狐GitLab Pages功能,以HTML格式查看测试报告:


参考资料

极狐GitLab自动化测试指南03——性能测试

https://wurang.net/auto-test03/

作者

Wu Rang

发布于

2022-02-26

更新于

2022-05-05

许可协议

评论