Розробка навантажувальних тестів для сайту (Locust)

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.
Розробка та обслуговування будь-яких видів сайтів:
Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Розробка навантажувальних тестів для сайту (Locust)
Середня
~2-3 робочих дні
Часті питання
Наші компетенції:
Етапи розробки
Останні роботи
  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851

Розроблення нагрузочних тестів для сайтів (Locust)

Locust — Python-інструмент нагрузочного тестування. Сценарії пишуться як звичайний Python-код, що дає максимальну гнучкість. Вбудований веб-інтерфейс для управління тестами в реальному часі. Легко масштабується горизонтально для високих нагрузок.

Встановлення

pip install locust

Базовий сценарій

# locustfile.py
from locust import HttpUser, task, between, events
import json
import random

class WebsiteUser(HttpUser):
    wait_time = between(1, 3)  # очікування між запитами 1-3 секунди

    def on_start(self):
        """Виконується при старті кожного користувача"""
        self.login()

    def login(self):
        response = self.client.post("/api/auth/login", json={
            "email": f"user{random.randint(1, 1000)}@test.com",
            "password": "testpassword",
        })
        if response.status_code == 200:
            self.token = response.json()["access_token"]
            self.client.headers.update({"Authorization": f"Bearer {self.token}"})
        else:
            self.token = None

    @task(3)  # вага 3 — виконується в 3 рази частіше
    def browse_products(self):
        page = random.randint(1, 10)
        with self.client.get(f"/api/products?page={page}", catch_response=True) as response:
            if response.status_code == 200:
                data = response.json()
                if "data" not in data:
                    response.failure("Missing 'data' key in response")
            else:
                response.failure(f"Got {response.status_code}")

    @task(2)
    def view_product(self):
        product_id = random.randint(1, 500)
        self.client.get(f"/api/products/{product_id}")

    @task(1)
    def create_order(self):
        if not self.token:
            return
        self.client.post("/api/orders", json={
            "product_id": random.randint(1, 100),
            "quantity": random.randint(1, 3),
        })

Користувацькі метрики

from locust import events
from locust.runners import MasterRunner

@events.request.add_listener
def on_request(request_type, name, response_time, response_length, response,
               context, exception, start_time, url, **kwargs):
    if exception:
        print(f"Request failed: {name} - {exception}")
    elif response_time > 2000:
        print(f"Slow request: {name} - {response_time}ms")


class FastApiUser(HttpUser):
    wait_time = between(0.5, 2)

    @task
    def search(self):
        start = time.time()
        with self.client.get("/api/search?q=laptop", catch_response=True) as response:
            duration = (time.time() - start) * 1000

            if response.status_code != 200:
                response.failure(f"Wrong status: {response.status_code}")
            elif duration > 1000:
                response.failure(f"Too slow: {duration:.0f}ms")

Кілька типів користувачів

class BrowsingUser(HttpUser):
    weight = 7  # 70% користувачів
    wait_time = between(2, 5)

    @task
    def browse(self):
        self.client.get("/api/products")

class PowerUser(HttpUser):
    weight = 3  # 30% користувачів
    wait_time = between(0.5, 1)

    @task
    def create_content(self):
        self.client.post("/api/products", json={
            "name": f"Product {random.randint(1, 9999)}",
            "price": random.uniform(100, 10000),
        })

Запуск тестів

# З веб-інтерфейсом
locust -f locustfile.py
# Відкрити http://localhost:8089

# Headless режим
locust -f locustfile.py \
    --headless \
    --users 100 \
    --spawn-rate 10 \
    --run-time 5m \
    --host https://staging.example.com \
    --html report.html \
    --csv results

# Distributed mode (кілька машин)
# Master
locust -f locustfile.py --master --expect-workers=3

# Workers (на інших серверах)
locust -f locustfile.py --worker --master-host=192.168.1.100

Порогові значення (assertions)

# locustfile.py
from locust import events

@events.quitting.add_listener
def assert_stats(environment, **kwargs):
    stats = environment.runner.stats
    total = stats.total

    if total.fail_ratio > 0.01:
        print(f"FAIL: Error rate {total.fail_ratio:.2%} > 1%")
        environment.process_exit_code = 1

    if total.avg_response_time > 500:
        print(f"FAIL: Avg response time {total.avg_response_time:.0f}ms > 500ms")
        environment.process_exit_code = 1

    p99 = total.get_response_time_percentile(0.99)
    if p99 > 2000:
        print(f"FAIL: p99 {p99:.0f}ms > 2000ms")
        environment.process_exit_code = 1

Інтеграція в CI/CD

# GitHub Actions
- name: Run Locust Load Test
  run: |
    locust -f locustfile.py \
      --headless \
      --users 50 \
      --spawn-rate 5 \
      --run-time 3m \
      --host ${{ vars.STAGING_URL }} \
      --html load-report.html
  continue-on-error: false

- name: Upload Report
  uses: actions/upload-artifact@v3
  with:
    name: load-test-report
    path: load-report.html

Строк реалізації

Написання 3–5 сценаріїв Locust з типами користувачів та ассертами: 2–4 дня.