基于 Python 的性能测试工具 locust (与 LR 的简单对比)

本文通过对比HP LoadRunner (LR) 和开源工具 Locust,介绍了如何使用Locust进行性能测试,并在相同并发用户情况下,对比两者在平均响应时间和TPS等方面的测试结果。Locust基于Python,支持分布式执行,适用于HTTP接口的测试。

目录

前言:

背景

基础

测试需求

服务器端

LR 中的测试脚本

locust 中的测试脚本

LR 中的测试过程和结果

Locust 中的测试过程和结果

结果比较

总结


前言:

Locust 是一种开源的性能测试工具,可以帮助我们快速地进行网站、应用程序等的性能测试和压力测试。

背景

最近自己开发了一个小的接口,功能测完了,突然想测下性能,原来做性能测试,我一直用的是 HP 的 LoadRunner,前一段时间正好看过 locust,想想就用这个来测测性能吧。
由于对 LR 比较熟,正好做个对比,这样更利于对新东西的理解。

基础

locust 的官网:Locust - A modern load testing framework

目前 locust 还只支持 Python 2 版本。

测试需求

验证在相同的服务器端的情况下,使用 LR 和 locust 分别进行性能测试,在相同并发用户的情况下,验证平均响应时间,TPS 值等性能测试指标的差异。
为了方便,使用 http 协议,一个 get 请求,一个 post 请求,交易比例为 1:1。

服务器端

为了简单易理解,用 Python 的 bottle 框架写了一个服务器端,2 个交易,一个 get,一个 post 请求,交易中加了 2 个不同的 sleep。
代码如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

__author__ = 'among,lifeng29@163.com'

from bottle import *
from time import sleep

app = Bottle()


@app.route('/transaction_1', method='GET')
def tr1():
    sleep(0.2)
    resp = dict()
    resp['status'] = 0
    resp['value'] = 'xxx'
    return resp


@app.route('/transaction_2', method='POST')
def tr2():
    parm1 = request.forms.get('parm1')
    parm2 = request.forms.get('parm2')
    sleep(0.5)
    resp = dict()
    resp['status'] = 0
    resp['value'] = 'yyy'
    return resp


run(app=app, server='cherrypy', host='0.0.0.0', port=7070, reloader=False, debug=False)

服务器端部署在一个单独的 Windows 的机器中,基于 Python 3,启动后,监听 7070 端口。

LR 中的测试脚本

在另外的一个 Windows 机器中,使用 LR 11,用的是 http/html 协议的脚本,主要代码如下:
用了 2 个 action,用于划分交易比例。
action1:

Action1()
{
    lr_start_transaction("get");
    web_reg_find("Text=xxx",
        LAST);
    web_custom_request("Head",
        "URL=http://10.0.244.108:7070/transaction_1", 
        "Method=GET",
        "Resource=0",
        "Referer=",
        LAST);
    lr_end_transaction("get", LR_AUTO);
    return 0;
}

action2:

Action2()
{
    lr_start_transaction("post");
    web_reg_find("Text=yyy",
        LAST);  
    web_custom_request("Head",
        "URL=http://10.0.244.108:7070/transaction_2", 
        "Method=POST",
        "Resource=0",
        "Referer=",
        "Body=parm1=123&parm2=abc",
        LAST);
    lr_end_transaction("post", LR_AUTO);
    return 0;
}

使用 1:1 的比例设置 2 个 transaction 的执行比例:

LR 中的执行方法,直接放到场景中,执行即可。

locust 中的测试脚本

在另外的 mac 中,使用 locust 执行测试,全部通过代码实现。代码如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

__author__ = 'among,lifeng29@163.com'

from locust import *

class mytest(TaskSet):
    @task(weight=1)
    def transaction_1(self):
        with self.client.get(name='get', url='/transaction_1', catch_response=True) as response:
            if 'xxx' in response.content:
                response.success()
            else:
                response.failure('error')

    @task(weight=1)
    def transaction_2(self):
        dt = {
            'parm1': '123',
            'parm2': 'abc'
        }

        with self.client.post(name='post', url='/transaction_2', data=dt, catch_response=True) as response:
            if 'yyy' in response.content:
                response.success()
            else:
                response.failure('error')


class myrun(HttpLocust):
    task_set = mytest
    host = 'http://10.0.244.108:7070'
    min_wait = 0
    max_wait = 0

具体的参数可以查看官方文档。

其中:

  1. 主类继承 HttpLocust,用于测试 http 协议的系统;
  2. min_wait 和 max_wait 用于设置执行 task 过程中的等待时间,相当于 LR 中 Pacing 的设置,这里都设置为 0;
  3. task 装饰器类似于 LR 中的事务,可以做嵌套;
  4. weight 相当于权重,如 2 个事务是 1:1,保持比例一致就行;
  5. 这里写了 2 个事务,分别为 get 和 post;对 response 的判断通过 python 的语法实现,类似于 LR 中的检查点。

执行方法,通过命令行启动:
如下图:

LR 中的测试过程和结果

测试过程:
直接设置并发用户数和加载方式,10 个用户并发,同时加载就可以了。

测试结果:
平均响应时间:

TPS:

事务:

Locust 中的测试过程和结果

测试过程:
使用浏览器打开http://127.0.0.1:8089

设置需要的并发用户数和用户加载策略。
这里设置相同的 10 用户并发,Hatch Rate 是每秒启动多少用户的意思。这里设置为 10,就是同时启动 10 个了。注意,这里不好设置执行多久,和 LR 不一样。(可以不启动浏览器,直接在启动参数中设置并发用户数,执行多少个事务后结束,具体用-h 可以看到帮助)

启动执行后:

其中,Average 中为平均响应时间等测试指标,最后一列的 reqs/sec 相当于 LR 中的 TPS。(这里 locust 把它叫做 rps),其他指标都比较好理解了。

最后的结果:
在 web 页面中可以下载原始的测试结果数据。
在停掉 python 命令后,在终端中也可以看到一些信息,最后的一行是百分之 X 的响应时间,表示百分之多少的交易在 XXX 响应时间内。
这里比 LR 中的要多点,包括了 50% 到 100% 的响应时间。

结果比较

在相同的服务器端环境,测试的结果值相似,没有多大的区别。
在设置交易比例的过程中,可以看到 get 和 post 交易的比例都存在差异。这个也无法避免(除非自己写脚本划分)。所以 tps 方面存在些差异。不过总体差距很小。

总结

性能测试,重点是考察并发用户数、响应时间、tps 这类指标。

一直用的是 LR,LR 在一起概念上更易于理解,在有 lr 的基础上,在看其他的工具,就比较容易了。

locust 也可以支持分布式执行(多执行机),用来简单测试这类 http 的接口,也算比较方便。
而且,locust 全部基于 Python 脚本,扩展性不错,号称可以测试任何协议和系统。

  作为一位过来人也是希望大家少走一些弯路

在这里我给大家分享一些自动化测试前进之路的必须品,希望能对你带来帮助。

(软件测试相关资料,自动化测试相关资料,技术问题答疑等等)

相信能使你更好的进步!

点击下方小卡片

<think>我们正在撰写一个基于Python的自动驾驶订单系统(如“萝卜快跑”)的软件测试项目描述。这包括简历中的项目描述、测试用例设计、自动化测试实践等内容。我们将参考提供的引用内容,特别是关于PO模式(页面对象模型)和Selenium自动化测试的部分。 项目目标:设计一个自动化测试框架,用于测试“萝卜快跑”订单系统的核心功能,如下单、订单状态跟踪、取消订单等。 步骤: 1. 项目概述:在简历中描述项目时,需要突出测试的范围、使用的技术和取得的成果。 2. 测试用例设计:设计关键的手动测试用例,覆盖核心业务场景。 3. 自动化测试实践:使用PO模式结合Selenium(如果是Web)或Appium(如果是移动应用)实现自动化测试。由于引用中提到了PO模式和Selenium,我们假设是Web应用。 由于引用[1]和[3]都是关于蓝桥杯自动化测试模拟赛的,其中使用了PO模式,我们可以借鉴其结构。 具体内容: 一、简历中的项目描述示例: 项目名称:萝卜快跑自动驾驶订单系统自动化测试 项目时间:2023年X月-2023年X月 项目描述: - 负责萝卜快跑订单系统的核心功能测试,包括用户登录、下单、订单状态查询、取消订单等模块。 - 设计并执行手动测试用例,覆盖正常流程、异常流程和边界条件,确保系统功能符合需求。 - 基于Python语言,使用Selenium WebDriver和PO模式(页面对象模型)搭建自动化测试框架,提高回归测试效率。 - 实现关键业务流程的自动化测试脚本,如下单流程,并集成到持续集成(CI)环境中,每日执行。 - 使用Allure生成测试报告,提升测试结果的可读性。 - 通过自动化测试发现并跟踪多个缺陷,提升产品质量。 二、测试用例设计(部分关键用例): 1. 用户登录: - 正常登录:使用正确的用户名和密码登录,验证登录成功并跳转到首页。 - 错误登录:使用错误的密码,验证系统提示正确的错误信息。 2. 下单流程: - 正常下单:选择起点和终点,选择车型,确认订单,验证订单生成成功并显示正确的订单信息。 - 未选择起点/终点:尝试下单,验证系统提示选择起点和终点。 3. 订单状态跟踪: - 下单后,查看订单状态是否为“等待接单”。 - 模拟司机接单,验证订单状态变为“已接单”。 4. 取消订单: - 在司机接单前取消订单,验证取消成功且状态变为“已取消”。 - 在司机接单后取消订单,验证系统提示无法取消。 三、自动化测试实践: 1. 框架选择:Python + Selenium + pytest + Allure 2. PO模式实现:每个页面封装为一个类,元素定位和操作封装在类的方法中。 例如,登录页面(login_page.py)可以这样实现(参考引用[3]): ```python from selenium.webdriver.common.by import By class LoginPage: def __init__(self, driver): self.driver = driver def input_username(self, username): self.driver.find_element(By.CSS_SELECTOR, 'input[name="username"]').clear() self.driver.find_element(By.CSS_SELECTOR, 'input[name="username"]').send_keys(username) def input_password(self, password): self.driver.find_element(By.CSS_SELECTOR, 'input[name="password"]').clear() self.driver.find_element(By.CSS_SELECTOR, 'input[name="password"]').send_keys(password) def click_login_button(self): self.driver.find_element(By.ID, 'btnSubmit').click() ``` 3. 测试用例(test_order.py)示例: ```python import pytest from pages.login_page import LoginPage from pages.order_page import OrderPage class TestOrder: @pytest.fixture(autouse=True) def setup(self, driver): self.driver = driver self.login_page = LoginPage(driver) self.order_page = OrderPage(driver) def test_successful_order(self): # 登录 self.login_page.input_username("test_user") self.login_page.input_password("123456") self.login_page.click_login_button() # 下单操作 self.order_page.select_start_point("A地点") self.order_page.select_end_point("B地点") self.order_page.select_car_type() self.order_page.submit_order() # 验证订单 assert self.order_page.get_order_status() == "等待接单" ``` 4. 集成持续集成:使用Jenkins定时执行测试,并生成Allure报告。 四、项目成果: - 构建了可维护的自动化测试框架,覆盖核心功能。 - 回归测试时间从X小时减少到Y分钟。 - 发现并跟踪了XX个缺陷,提升了产品质量。 注意:由于实际项目中的页面元素和流程可能不同,以上代码仅作示例。需要根据实际系统进行调整。 相关问题: 1. 在PO模式中,如何处理页面跳转? 2. 如何设计数据驱动的测试用例? 3. 在自动化测试中,如何处理动态元素?</think>### 基于Python的自动驾驶订单系统(萝卜快跑)软件测试项目实践指南 #### 一、简历项目描述示例(突出测试能力) **项目名称**:萝卜快跑自动驾驶订单系统自动化测试 **测试周期**:2023.03-2023.08 **项目描述**: - 搭建基于Python的自动化测试框架(PO模式+Selenium+Pytest),覆盖用户下单、订单追踪、异常取消等核心业务流程 - 设计并执行120+测试用例,通过等价类划分和边界值分析发现17个关键缺陷,缺陷修复率达95% - 实现API接口自动化测试(Requests库),完成订单状态变更、计费规则验证等关键接口测试 - 集成Allure报告和Jenkins持续集成,测试效率提升60%,回归测试时间从8小时缩短至30分钟 - 针对高并发场景设计压力测试方案(Locust工具),验证系统在500+并发订单下的稳定性 #### 二、测试用例设计(关键场景) 1. **用户端功能测试** ```markdown TC01: 新用户首次下单流程 步骤:定位服务→选择车型→确认订单→支付 预期:生成待接单状态订单,推送至司机端 TC02: 订单状态流转验证 步骤:待接单→已接单→行程中→已完成 预期:各状态计时准确,状态变更实时同步 TC03: 异常取消场景 步骤:司机接单前取消/接单后取消/行程中取消 预期:按计费规则扣费,推送取消原因通知 ``` 2. **计费规则测试矩阵** | 里程(km) | 时段 | 车型 | 预期费用 | |----------|------------|----------|----------| | 3 | 平峰(10:00)| 经济型 | ¥15 | | 12 | 高峰(18:30)| 豪华型 | ¥48 | | 0.5 | 夜间(23:00)| 舒适型 | ¥13(起步价)| 3. **压力测试场景** - 并发场景:300用户同时发起订单请求 - 验证指标:订单创建成功率 ≥99.9%,响应时间 ≤1.5s - 异常注入:模拟GPS信号丢失时订单冻结机制 #### 三、自动化测试实现方案 1. **PO模式框架结构** ```bash framework/ ├── pages/ # 页面对象封装 │ ├── order_page.py # 订单操作类 │ └── login_page.py # 登录操作类 ├── testcases/ # 测试用例集 │ ├── test_order_creation.py │ └── test_payment.py ├── utils/ # 工具类 │ ├── config_reader.py │ └── log_util.py └── reports/ # Allure测试报告 ``` 2. **订单页面对象示例(order_page.py)** ```python from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait class OrderPage: def __init__(self, driver): self.driver = driver self.wait = WebDriverWait(driver, 10) def select_car_type(self, car_type="economy"): # PO模式封装元素操作 locator = f"//div[@data-type='{car_type}']" self.wait.until(EC.element_to_be_clickable((By.XPATH, locator))).click() def set_destination(self, start, end): self.driver.find_element(By.ID, "start-input").send_keys(start) self.driver.find_element(By.ID, "end-input").send_keys(end) self.driver.find_element(By.CSS_SELECTOR, ".confirm-btn").click() def submit_order(self): # 处理订单提交后的异步加载 self.driver.find_element(By.ID, "submit-order").click() self.wait.until(EC.visibility_of_element_located( (By.CLASS_NAME, "order-status") )) ``` 3. **API接口测试示例(计费规则验证)** ```python import requests import pytest @pytest.mark.parametrize("distance, expected_fee", [(5, 18), (10, 30)]) def test_fee_calculation(distance, expected_fee): url = "https://api.luobokuaipao.com/fee" params = {"distance": distance, "car_type": "standard"} response = requests.get(url, params=params) # 验证计费逻辑 assert response.status_code == 200 assert response.json()["data"]["amount"] == expected_fee assert response.json()["data"]["currency"] == "CNY" ``` #### 四、测试实践关键点 1. **特殊场景处理** - 使用Selenium的`expected_conditions`处理地图加载异步等待 - 通过`pytest.parametrize`实现多城市计价参数化测试 - 模拟网络延迟:`driver.set_network_conditions(latency=1000)` 验证弱网下单 2. **持续集成流程** ```mermaid graph LR A[代码提交] --> B[Jenkins触发] B --> C{测试环境部署} C --> D[执行自动化测试] D --> E[生成Allure报告] E --> F[钉钉通知结果] ``` 3. **测试数据管理** - 主流城市坐标数据库(北京/上海/广州) - 订单状态机测试数据集: ```json { "valid_transitions": [ {"from": "PENDING", "to": "ACCEPTED"}, {"from": "ON_TRIP", "to": "COMPLETED"} ], "invalid_transitions": [ {"from": "COMPLETED", "to": "CANCELLED"} ] } ``` #### 五、项目难点解决方案 1. **定位动态地图元素** ```python # 使用相对定位解决地图坐标漂移 marker = driver.find_element(By.CLASS_NAME, "start-marker") ActionChains(driver).move_to_element(marker).click().perform() ``` 2. **订单状态同步验证** 双端校验方案: ```python def verify_order_sync(order_id): user_status = get_user_order_status(order_id) # 用户端API driver_status = get_driver_order_status(order_id) # 司机端API assert user_status == driver_status, "状态不同步" ``` 3. **计费精度验证** ```python # 使用decimal避免浮点数误差 from decimal import Decimal assert Decimal(actual_fee) == Decimal("29.5") ``` --- ### 相关问题 1. 如何设计自动驾驶订单系统的异常场景测试用例? 2. 在PO模式中如何处理地图类应用的元素定位问题? 3. 如何验证订单系统在高并发场景下的数据一致性? 4. 自动驾驶订单测试需要哪些特殊测试设备或环境? 5. 如何建立订单系统的全链路监控体系? [^1]: 模拟赛 2 期 自动化测试python——第十五届蓝桥杯(软件测试) [^2]: Python接口自动化测试框架 [^3]: 模拟赛 1 期 自动化测试python——第十五届蓝桥杯(软件测试)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值