Он реализован на чистом Python и представляет собой инструмент распределенного пользовательского нагрузочного тестирования. Использование клиента на основе библиотеки Requests для инициирования запросов значительно упрощает написание сценариев; он отказывается от процессов и потоков при моделировании параллелизма и полностью управляем по времени, используя неблокирующий ввод-вывод и сопрограммы, предоставляемые сопрограммами (gevent), для реализации параллельных запросов на одном этапе. сетевой слой. Таким образом, одно нажатие может генерировать тысячи одновременных запросов.
Функции:
Поддерживаемые версии Python: 3.6, 3.7, 3.8.
pip install -U locust==2.5.1
#pip install -U locust==2.5.1 -i https://pypi.tuna.tsinghua.edu.cn/simple
from locust import HttpUser, task, between
# Эквивалентно моделированию пользователя
class WebUser(HttpUser):
# Адрес сервера
host = 'http://localhost:8000'
# Время ожидания перед следующим заданием. Изучите время обдумывания для пользователя шаблона.
wait_time = between(3, 5) # Здесь используется случайный 3,5 секунды
# Определите тестовую задачу, похожую на сэмплер.
@task(1)
def info(self):
# Получить информацию о пользователе
self.client.get('/info/')
@task(10)
def addresses(self):
# Получить адрес пользователя
self.client.get('/addresses/')
def on_start(self):
# тест Доосуществлятьиздействовать print('Вход пользователя')
auth = {'username': 'root', 'password': 'root1234'}
self.client.post('/login/', json=auth)
def on_stop(self):
# тест Заканчиватьосуществлятьиздействовать print('Пользователь вышел')
self.client.delete('/logout/')
locust
Он автоматически найдет имя locustfile.py
из файлаlocust -f xxx/locustfile.py
# Запускать напрямую
locust
# Укажите файл
locust -f xxx/locustfile.py
Затем откройте браузер, прямойсуществовать Ввод через браузерhttp://localhost:8089ОткрытьUIинтерфейс, Интерфейс выглядит следующим образом:
locust -f locustfile.py --headless -u 100 -r 10 -t 10s
from locust import User, events, task, between
import random
def success_call(name, recvText, total_time):
events.request_success.fire(
request_type="[Success]",
name=name,
response_time=total_time,
response_length=len(recvText)
)
def fail_call(name, total_time):
events.request_failure.fire(
request_type="[Fail]",
name=name,
response_time=total_time,
response_length=0,
exception=Exception(),
)
class MyUser(User):
wait_time = between(1, 5)
@task(1)
def job1(self):
print('This is job 1')
self.sendMsg("job1", 'This is job 2')
@task(2)
def job2(self):
print('This is job 2')
self.sendMsg("job2", 'This is job 2')
def sendMsg(self, methodname, msg):
num = random.randint(0, 2)
time = random.randint(10, 50)
if (num == 0):
fail_call(methodname, time)
else:
success_call(methodname, msg, time);
осуществлять
locust -f test4.py --autostart --autoquit 0 -u 1 -r 3 --run-time 10s
в
request_type
Метод запроса,Здесь для удобства понимания,прямойиспользоватьиз[Success]
и[Fail]
,отличать успехизпроситьинеудачаизпросить,Только после успеха или неудачи вызывается обратный вызов,саранча засчитает это.Уведомление:
Все задачи не могут быть методами.
результат:
Locus запускает несколько процессов, использовать --master
Команда запускает основной процесс, использовать --worker
Запустить подчиненный процесс
Главный процесс управляет подчиненным процессом и собирает результаты процессизтестирования, а подчиненный процесс отвечает за изучение теста и передает результаты главному процессу.
Запустите основной процесс без интерфейса
locust -f locustfile.py --master --headless --master-bind-host=127.0.0.1 --master-bind-port=8090 -t 15s -u 5 -r 1
--master
Укажите, что текущий хост — процесс--master-bind-host=[ip адрес]
Укажите основную привязку процесса и задрес--master-bind-port=[номер порта]
Укажите основную привязку процесса по номеру портаПосле запуска, если текущего подчиненного устройства из процесса нет, отобразится сообщение «Ожидание подчиненного устройства от процесса». Скрипт изучения доступен при запуске из процесса.
Запустите бесинтерфейсный подчиненный процесс:
locust -f locustfile.py --worker --master-host=127.0.0.1 --master-port=8090 --headless
--worker
Указывает, что текущее местоположение принадлежит процессу.--master-host=[ip адрес]
Указывает на необходимость подключения к основному процессизу. ip адрес--master-port=[номер порта]
Указывает на необходимость подключения к основному процессизу.портПосле запуска процесса начнется изучениетест и основной процесс подсчитает результаты.
для web Для веб-сайтов пользователи обычно могут выполнять несколько действий на одной странице веб-сайта, и эти действия обычно преследуют определенную цель. Например, на странице регистрации пользователи могут выполнять действия: Убедитесь, что имя пользователя и номер мобильного телефона повторяются, обновите графический проверочный код, получите проверочный код мобильного телефона и т. д. Целью этих действий является завершение регистрации пользователя. Мы можем объединить эти действия вместе.
В locust мы используем класс TaskSet для объединения нескольких действий, а затем вводим набор задач в объект HttpUser, добавляя класс набора задач в список атрибутов задач.
Наборы задач также могут быть вложенными. Мы добавляем другие классы набора задач, которые будут вложены в атрибут задач набора задач. Аналогично: Домашняя страница веб-сайта содержит страницу входа пользователя, а страница входа пользователя содержит страницу регистрации пользователя.
import uuid
from locust import HttpUser, task, between, TaskSet
# зарегистрироваться
class RegistTaskSet(TaskSet):
# Имя пользователя дублируется?
@task
def username_count(self):
username = 'zhangsan'
self.client.get(f'/usernames/{username}/count/')
# Дублируется ли номер мобильного телефона?
@task
def mobile_count(self):
mobile = '13712345678'
self.client.get(f'/mobiles/{mobile}/count/')
# Получить графический код подтверждения
@task
def image_codes(self):
image_code_id = str(uuid.uuid4())
self.client.get(f'/image_codes/{image_code_id}/')
@task
def stop(self):
print('Выход из текущего набора действий')
self.interrupt()
# Авторизоваться
class UserLoginTaskSet(TaskSet):
# Вложенный пользователь зарегистрироваться
tasks = [RegistTaskSet]
@task
def username_login(self):
auth = {'username': 'root', 'password': 'root1234'}
self.client.post('/login/', json=auth)
@task
def stop(self):
print('Выход из текущего набора действий')
self.interrupt()
# Выдавать себя за пользователя
class WebUser(HttpUser):
# Сумка Содержит пользователей Авторизоваться
tasks = [UserLoginTaskSet]
# Адрес сервера
host = 'http://localhost:8000'
# Время ожидания перед следующим заданием. Изучите время обдумывания для пользователя шаблона.
wait_time = between(3, 5) # Здесь используется случайный 3,5 секунды
@task
def search(self):
# поиск
self.client.get('/search/')
мы HttpUser а также TaskSet После определения действия саранча заключается в случайном выборе действия из этих действий для изучения.,Иногда мы хотим, чтобы действия пользователя были упорядоченными,например:
1. Проверьте, не дублируется ли имя пользователя. 2. Проверьте, дублируется ли номер мобильного телефона. 3. Проверьте и получите графический проверочный код. 4. Получите код подтверждения мобильного телефона. 5.Зарегистрируйтесь На этом этапе вам необходимо определить набор действий через SequentialTaskSet, который будет вызываться один раз в том порядке, в котором определены задачи.
from locust import HttpUser, task, between, SequentialTaskSet
class RegistSeqTaskSet(SequentialTaskSet):
# Имя пользователя дублируется?
@task
def username_count(self):
print('Проверить имя пользователя')
username = 'zhangsan'
self.client.get(f'/usernames/{username}/count/')
# Дублируется ли номер мобильного телефона?
@task
def mobile_count(self):
print('Подтвердить номер мобильного телефона')
mobile = '13712345678'
self.client.get(f'/mobiles/{mobile}/count/')
# Получить графический код подтверждения
@task
def image_codes(self):
print('Получить графический код подтверждения')
image_code_id = str(uuid.uuid4())
self.client.get(f'/image_codes/{image_code_id}/')
# Выдавать себя за пользователя
class WebUser(HttpUser):
# Сумка Содержит пользователей Авторизоваться
tasks = [RegistSeqTaskSet]
# Адрес сервера
host = 'http://localhost:8000'
# Время ожидания перед следующим заданием. Изучите время обдумывания для пользователя шаблона.
wait_time = between(3, 5) # Здесь используется случайный 3,5 секунды
Нам нужно определить, завершился ли запрос неудачно или успешно. Нам нужно добавить catch_response=True в параметры запроса, чтобы метод запроса возвращал диспетчер контекста.
Этот контекстный менеджер возвращает объект ответа. Мы отмечаем этот запрос как неудавшийся, вызывая ошибку (сообщение) объекта ответа.
проходить catch_response=True параметры для продолженияутверждение。
from locust import HttpUser, task, between
class WebUser(HttpUser):
wait_time = between(1, 5)
host = 'http://localhost:8000'
@task
def info(self):
with self.client.get('/info/', catch_response=True) as resp:
res = resp.json()
if res['code'] != 0:
resp.failure(res['errmsg'])
Подключение к библиотеке WSiz имеет поддержку асинхронногоIOiz.,Рекомендуем эту библиотеку в проекте,ноВам все равно придется выбирать библиотеку синхронныйиз при тестировании давления.。
Установить
pip install websockets
пример кода
import asyncio
import websockets
import json
import random
async def mytest():
async with websockets.connect('wss://sockettest.xhkjedu.com/ws') as websocket:
num = random.randint(0, 10000000)
msg = {
"b": {"num": num},
"c": 123456,
}
msgstr = json.dumps(msg)
await websocket.send(msgstr)
print(f"↑: {msgstr}")
greeting = await websocket.recv()
print(f"↓: {greeting}")
asyncio.get_event_loop().run_until_complete(mytest())
Официальный адрес сайта
https://pypi.org/project/websocket-client/
Установить
pip install websocket-client
Пример
from websocket import create_connection
import json
import random
ws = create_connection("wss://sockettest.xhkjedu.com/ws")
num = random.randint(0, 10000000)
msg = {
"b": {"num": num},
"c": 123456,
}
msgstr = json.dumps(msg)
print("Sending " + msgstr)
ws.send(msgstr)
result = ws.recv()
print("Received '%s'" % result)
ws.close()
import websocket
def on_message(ws, message):
print(ws)
print(message)
def on_error(ws, error):
print(ws)
print(error)
def on_close(ws):
print(ws)
print("### closed ###")
websocket.enableTrace(True)
ws = websocket.WebSocketApp("ws://127.0.0.1:8888/track",
on_message=on_message,
on_error=on_error,
on_close=on_close)
ws.run_forever()
Jmeter хочет интерфейс testwebsocket,Нужно сначала скачать Установитьодинwebsocket samplers by peter doornbosch
изплагин
Поскольку locust реализован в коде, любой тест можно выполнить, обратившись к соответствующей библиотеке.
from locust import User, task, events
import time
from websocket import create_connection
import json
import random
def success_call(name, recvText, total_time):
events.request_success.fire(
request_type="[Success]",
name=name,
response_time=total_time,
response_length=len(recvText)
)
def fail_call(name, total_time, e):
events.request_failure.fire(
request_type="[Fail]",
name=name,
response_time=total_time,
response_length=0,
exception=e,
)
class WebSocketClient(object):
def __init__(self, host):
self.host = host
self.ws = None
def connect(self, burl):
self.ws = create_connection(burl)
def recv(self):
return self.ws.recv()
def send(self, msg):
self.ws.send(msg)
class WebsocketUser(User):
abstract = True
def __init__(self, *args, **kwargs):
super(WebsocketUser, self).__init__(*args, **kwargs)
self.client = WebSocketClient(self.host)
self.client._locust_environment = self.environment
class ApiUser(WebsocketUser):
host = "wss://sockettest.xhkjedu.com/"
@task(1)
def pft(self):
# wss адрес
self.url = 'wss://sockettest.xhkjedu.com/ws'
print("перед подключением")
start_time = time.time()
try:
self.client.connect(self.url)
print("После подключения")
# Отправить запрос на подписку
num = random.randint(0, 10000000)
msg = {
"b": {"num": num},
"c": 123456,
}
msgstr = json.dumps(msg)
self.client.send(msgstr)
print(f"↑: {msgstr}")
greeting = self.client.recv()
print(f"↓: {greeting}")
except Exception as e:
total_time = int((time.time() - start_time) * 1000)
fail_call("Send", total_time, e)
else:
total_time = int((time.time() - start_time) * 1000)
success_call("Send", "success", total_time)
тест
locust -f main.py -u 5000 -r 300
Доступ через Интернет
Или не используйте графический интерфейс
locust -f main.py --autostart --autoquit 0 -u 1 -r 3 --run-time 10s
в
--autostart
Запускать автоматически НетиспользоватьWebUI--autoquit 0
иautostart
соответствоватьиспользовать,Через какое время тест завершается после завершения?,Единицей измерения следующих чисел являются секунды.,Если вы его не установите, выйти можно только по CTRL+C.-u 1
Максимальное количество пользователей-r 3
Количество пользователей, созданных в секунду, количество пользователей, созданных в секунду количество пользователи не будут создаваться снова после того же--run-time 10s
Испытание давлением изолировать время