Locust性能测试实战:从0到1编写登录接口压测脚本 | 超详细教程

作者:c_chun 发布时间: 2025-12-10 阅读量:6 评论数:0

在日常的接口测试中,性能测试是验证系统稳定性的关键环节。相比于LoadRunner等重型商业工具,Locust凭借“Python编写、高并发、轻量易用”的特点,成为中小团队和个人开发者的首选。本文将以登录接口性能测试为例,从零讲解Locust的核心概念和实战用法,即使是性能测试新手也能快速上手。

一、Locust是什么?为什么选它?

Locust是一款基于Python的开源性能测试工具,核心优势如下:

  • 纯Python编写:无需学习复杂的专有脚本,用熟悉的Python语法即可编写测试逻辑,灵活度拉满;

  • 高并发特性:基于协程模型(gevent),单台普通服务器可模拟数万并发用户,资源占用远低于传统线程/进程模型工具;

  • Web可视化控制台:一键启动,直观查看响应时间、TPS、错误率等核心指标;

  • 无侵入性:无需在被测系统中部署任何代理,仅通过HTTP请求压测,对业务无影响;

  • 完全免费:开源无授权费用,适合小团队/个人使用。

本文将以“小程序登录接口(/wx/auth/login)”为测试目标,完整演示Locust从环境搭建到结果分析的全流程。

二、环境准备

1. 基础环境

确保本地已安装Python(3.7+版本,推荐3.9/3.10),验证方式:

python --version  # 或 python3 --version

2. 安装Locust

使用pip快速安装Locust:

pip install locust

验证安装成功:

locust -V  # 输出Locust版本号即安装成功(如locust 2.42.6)

三、Locust核心概念(新手必懂)

在编写脚本前,先理解Locust的3个核心概念,结合登录场景通俗解释:

核心概念

含义

对应登录场景示例

HttpUser

虚拟用户类,所有压测脚本的基类,封装了HTTP请求方法(post/get等)

模拟一个用户发起登录请求

@task

任务装饰器,标记用户要执行的核心操作,可设置任务权重

标记“登录”为用户的核心操作

wait_time

虚拟用户执行完任务后的等待时间,模拟真实用户的操作间隔

用户登录后,等待1-3秒再发起下一次登录(模拟真实操作节奏)

host

被测系统的基础域名/IP,避免脚本中重复写完整URL

配置为http://112.126.74.xxx

on_start

生命周期钩子,虚拟用户启动时执行的初始化操作(可选)

启动时从用户池随机选择一个测试账号

四、实战:编写登录接口压测脚本

1. 测试目标说明

本次测试的登录接口信息:

  • 接口地址:/wx/auth/login

  • 请求方式:POST

  • 请求体:{"username": "user124", "password": "user123"}

  • 响应成功标识:errno=0errmsg="成功"

  • 测试数据:从test_users.json中读取100个测试用户账号

2. 完整脚本编写

新建login_perf_test.py文件,代码如下(含详细注释):

import json
import random
from locust import HttpUser, task, between, events
from locust.exception import StopUser

# ---------------------- 1. 全局初始化:加载测试用户数据 ----------------------
USER_LIST = []

def load_user_data():
    """从JSON文件加载测试用户数据(username)"""
    try:
        with open("test_users.json", "r", encoding="utf-8") as f:
            data = json.load(f)
            # 提取所有有效用户名,避免空值
            user_names = [user["username"] for user in data if "username" in user and user["username"]]
            print(f"成功加载 {len(user_names)} 个测试用户")
            return user_names
    except FileNotFoundError:
        print("❌ 错误:未找到test_users.json文件,请确认文件路径")
        return []
    except json.JSONDecodeError:
        print("❌ 错误:test_users.json格式无效,请检查JSON语法")
        return []

# 初始化加载用户数据
USER_LIST = load_user_data()

# ---------------------- 2. 定义虚拟用户行为 ----------------------
class LoginUser(HttpUser):
    """登录接口虚拟用户类:模拟用户发起登录请求"""
    # 被测系统基础地址(避免重复写完整URL)
    host = "http://112.126.74.xxx"
    # 每个用户执行完任务后,随机等待1-3秒(模拟真实用户操作间隔)
    wait_time = between(1, 3)

    def on_start(self):
        """用户启动时执行:随机选择一个测试用户,避免重复登录"""
        if not USER_LIST:
            print("❌ 无可用测试用户,停止当前虚拟用户")
            raise StopUser()  # 终止当前用户,避免无效请求
        # 随机选一个用户,密码统一为user123(根据实际场景调整)
        self.username = random.choice(USER_LIST)
        self.password = "user123"

    @task  # 标记为核心测试任务
    def login_api_test(self):
        """核心任务:调用登录接口,并验证响应结果"""
        # 1. 定义接口地址(拼接host后完整地址:http://112.126.74.xxx/wx/auth/login)
        url = "/wx/auth/login"
        
        # 2. 设置请求头(模拟真实前端请求,按实际接口要求调整)
        headers = {
            "accept": "application/json, text/plain, */*",
            "accept-encoding": "gzip, deflate",
            "accept-language": "zh-CN,zh;q=0.9,en;q=0.8",
            "content-type": "application/json",
            "origin": "http://112.126.74.xxx",
            "referer": "http://112.126.74.xxx/mall/",
            "user-agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 KHTML, like Gecko Version/18.5 Mobile/15E148 Safari/604.1"
        }
        
        # 3. 构造请求体(使用随机选择的用户名)
        payload = {
            "username": self.username,
            "password": self.password
        }

        # 4. 发送POST请求,并捕获响应(用于断言验证)
        with self.client.post(
            url=url,
            json=payload,  # 自动序列化JSON,无需手动转字符串
            headers=headers,
            catch_response=True,  # 开启响应捕获,便于自定义断言
            name="登录接口"  # 测试报告中显示的任务名称,便于区分
        ) as response:
            # 5. 响应结果断言(验证登录是否成功)
            try:
                res_json = response.json()
                # 断言1:响应状态码为200
                if response.status_code != 200:
                    response.failure(f"状态码错误:{response.status_code} | 用户:{self.username}")
                # 断言2:响应errno为0(接口自定义成功标识)
                elif res_json.get("errno") != 0:
                    response.failure(f"登录失败:{res_json.get('errmsg')} | 用户:{self.username}")
                # 断言通过,标记为成功
                else:
                    response.success()
            # 异常处理:响应不是JSON格式
            except json.JSONDecodeError:
                response.failure(f"响应非JSON格式 | 用户:{self.username}")
            # 其他未知异常
            except Exception as e:
                response.failure(f"处理响应出错:{str(e)} | 用户:{self.username}")

# ---------------------- 3. 测试生命周期钩子(可选) ----------------------
@events.test_start.add_listener
def on_test_start(environment, **kwargs):
    """测试开始时执行:打印测试信息"""
    print(f"\n🚀 登录接口性能测试开始 | 测试用户数:{len(USER_LIST)}")

@events.test_stop.add_listener
def on_test_stop(environment,** kwargs):
    """测试结束时执行:打印测试总结"""
    print("\n🛑 登录接口性能测试结束 | 请查看测试报告分析结果")

3. 脚本核心说明

  • 数据加载:通过load_user_data函数读取test_users.json中的测试用户,避免硬编码账号,提升脚本灵活性;

  • 用户行为LoginUser类继承HttpUser,通过on_start初始化用户账号,@task标记登录任务;

  • 响应断言:开启catch_response=True后,可自定义成功/失败判定规则,精准统计登录接口的错误率;

  • 生命周期钩子test_start/test_stop用于打印测试日志,方便排查问题。

四、运行Locust脚本

Locust支持两种运行方式:Web控制台模式(推荐新手)无界面模式(适合自动化)

1. Web控制台模式(可视化操作)

在脚本所在目录执行命令:

locust -f login_perf_test.py

执行成功后,终端会输出:

[2025-12-XX XX:XX:XX] INFO/locust.main: Starting web interface at http://localhost:8089

打开浏览器访问http://localhost:8089,进入Locust控制台:

  • Number of users:总并发虚拟用户数(推荐填50,符合常规接口压测场景);

  • Spawn rate:每秒启动的用户数(推荐填5,10秒达到50并发,避免瞬间压垮服务器);

  • Host:被测系统地址(脚本中已定义,此处可留空);

点击「Start swarming」开始测试。

2. 无界面模式(适合CI/CD或后台运行)

如果不需要可视化控制台,可直接指定参数运行,测试结束后自动生成报告:

# 50并发用户,每秒启动5个,运行20分钟,无界面模式
locust -f login_perf_test.py --headless -u 50 -r 5 --run-time=20m

核心参数说明:

参数

含义

--headless

无界面模式

-u

总并发用户数

-r

每秒启动的用户数

--run-time

测试运行时长(5m=5分钟)

五、分析测试结果

Locust Web控制台提供了4个核心标签页,重点关注前3个:

1. Statistics(统计概览)

核心指标解读(登录接口重点关注):

  • Request name:任务名称(此处为“登录接口”);

  • Requests/s:TPS(每秒处理的请求数),越高说明接口吞吐量越好;

  • Median:响应时间中位数(50%的请求响应时间),登录接口建议≤500ms;

  • 95%ile:95%请求的响应时间(核心指标,反映绝大多数用户的体验);

  • Failure %:错误率,登录接口需控制为0%,否则说明接口存在问题。

2. Charts(趋势图表)

直观查看:

  • 响应时间随并发的变化趋势;

  • TPS的波动情况;

  • 虚拟用户数的增长曲线。

3. Failures(失败请求)

若存在失败请求,此处会列出具体原因(如“状态码错误”“登录失败”),便于定位接口问题。

六、Locust进阶技巧(可选)

  1. 参数化优化:除了从JSON读取数据,还可从CSV/数据库加载测试用户,提升数据多样性;

  2. 分布式压测:多台机器启动Locust,模拟10万+级并发(适合大型系统);

  3. 结果导出:将测试结果导出为CSV/HTML,便于后续分析和汇报;

  4. 自定义指标:添加响应时间、TPS的自定义监控,满足个性化需求。

七、总结

本文以登录接口为例,完整讲解了Locust的环境搭建、核心概念、脚本编写、运行方式和结果分析。核心要点回顾:

  1. Locust基于Python,轻量且高并发,适合中小团队做接口性能测试;

  2. 核心逻辑是“定义虚拟用户类 + 标记测试任务 + 验证响应结果”;

  3. 运行时需合理设置并发数(-u)和启动速率(-r),避免测试结果失真;

  4. 登录接口重点关注95%响应时间和错误率,确保接口稳定性。

相比于传统性能测试工具,Locust的优势在于“简单、灵活、易扩展”,只要掌握基础Python语法,就能快速适配各类接口的性能测试场景。建议从简单接口(如登录、查询)入手,逐步尝试复杂场景(如下单、支付),快速掌握Locust的使用精髓。

评论