perf-skills 1.0.3 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,133 +1,133 @@
1
- # Locust Reference
2
-
3
- > Targets: Locust 2.20+, Python 3.9+
4
-
5
- Locust is a Python-based, open-source load testing tool. Tests are plain Python code — no DSL, no XML. It supports distributed testing and has a built-in web UI.
6
-
7
- ---
8
-
9
- ## Core Concepts
10
-
11
- | Concept | Description |
12
- |---|---|
13
- | **User class** | Defines behavior of a simulated user |
14
- | **TaskSet** | Group of tasks; can be nested |
15
- | **task decorator** | Marks a method as a task with optional weight |
16
- | **wait_time** | Think time between tasks |
17
- | **HttpUser** | Preconfigured User with HTTP client |
18
- | **FastHttpUser** | High-performance HTTP client (gevent-based) |
19
- | **events** | Hooks for setup, teardown, request success/failure |
20
-
21
- ---
22
-
23
- ## Basic Script
24
-
25
- ```python
26
- from locust import HttpUser, task, between
27
- import json, random
28
-
29
- class ShopUser(HttpUser):
30
- wait_time = between(1, 4) # Think time: 1–4 seconds (uniform random)
31
- host = "https://api.example.com"
32
-
33
- def on_start(self):
34
- """Runs once per VU at startup"""
35
- res = self.client.post("/auth/login", json={
36
- "username": f"user{random.randint(1, 1000)}@test.com",
37
- "password": "testpass123"
38
- })
39
- self.token = res.json()["access_token"]
40
- self.client.headers.update({"Authorization": f"Bearer {self.token}"})
41
-
42
- @task(3) # Weight: called 3x more than weight-1 tasks
43
- def browse_products(self):
44
- self.client.get("/products", name="GET /products")
45
-
46
- @task(1)
47
- def add_to_cart(self):
48
- product_id = random.randint(1, 100)
49
- with self.client.post(
50
- f"/cart/items",
51
- json={"productId": product_id, "qty": 1},
52
- catch_response=True, # Manually handle response
53
- name="POST /cart/items"
54
- ) as response:
55
- if response.status_code == 200:
56
- response.success()
57
- else:
58
- response.failure(f"Expected 200, got {response.status_code}")
59
-
60
- def on_stop(self):
61
- self.client.post("/auth/logout")
62
- ```
63
-
64
- ---
65
-
66
- ## Running Locust
67
-
68
- ```bash
69
- # Web UI mode
70
- locust -f locustfile.py --host https://api.example.com
71
-
72
- # Headless (CLI) mode
73
- locust -f locustfile.py \
74
- --headless \
75
- --users 100 \
76
- --spawn-rate 10 \
77
- --run-time 5m \
78
- --host https://api.example.com \
79
- --html report.html \
80
- --csv results
81
-
82
- # Distributed mode
83
- # On master:
84
- locust -f locustfile.py --master --users 1000 --spawn-rate 50
85
- # On each worker:
86
- locust -f locustfile.py --worker --master-host=<master-ip>
87
- ```
88
-
89
- ---
90
-
91
- ## Custom Wait Times
92
-
93
- ```python
94
- from locust import constant, constant_pacing, between, constant_throughput
95
-
96
- wait_time = between(1, 5) # Uniform random 1–5s
97
- wait_time = constant(2) # Fixed 2s
98
- wait_time = constant_pacing(10) # Paces to 1 iteration per 10s (handles slow responses)
99
- wait_time = constant_throughput(0.1) # Target 0.1 RPS per VU (10s average)
100
- ```
101
-
102
- ---
103
-
104
- ## Custom Events and Hooks
105
-
106
- ```python
107
- from locust import events
108
-
109
- @events.test_start.add_listener
110
- def on_test_start(environment, **kwargs):
111
- print("Test starting — seeding test data")
112
-
113
- @events.request.add_listener
114
- def on_request(request_type, name, response_time, response_length, exception, **kwargs):
115
- if exception:
116
- print(f"FAILED: {name} — {exception}")
117
-
118
- @events.test_stop.add_listener
119
- def on_test_stop(environment, **kwargs):
120
- print("Test finished — cleaning up data")
121
- ```
122
-
123
- ---
124
-
125
- ## Locust-Specific Tips
126
-
127
- - Always use `name=` parameter to group parameterized URLs (e.g., `/products/123` → `name="GET /products/{id}"`).
128
- - Use `catch_response=True` for custom validation — HTTP 200 with error body passes silently otherwise.
129
- - Use `FastHttpUser` instead of `HttpUser` for CPU-bound or high-throughput scenarios.
130
- - Use distributed mode above 500–1000 VUs — a single worker process saturates one CPU core.
131
-
132
- > For anti-patterns, assertions, think time, and parameterization principles, see **Key Principles** in `SKILL.md`.
133
- > For CI/CD integration and distributed execution details, see `../topics/test-execution.md`.
1
+ # Locust Reference
2
+
3
+ > Targets: Locust 2.20+, Python 3.9+
4
+
5
+ Locust is a Python-based, open-source load testing tool. Tests are plain Python code - no DSL, no XML. It supports distributed testing and has a built-in web UI.
6
+
7
+ ---
8
+
9
+ ## Core Concepts
10
+
11
+ | Concept | Description |
12
+ |---|---|
13
+ | **User class** | Defines behavior of a simulated user |
14
+ | **TaskSet** | Group of tasks; can be nested |
15
+ | **task decorator** | Marks a method as a task with optional weight |
16
+ | **wait_time** | Think time between tasks |
17
+ | **HttpUser** | Preconfigured User with HTTP client |
18
+ | **FastHttpUser** | High-performance HTTP client (gevent-based) |
19
+ | **events** | Hooks for setup, teardown, request success/failure |
20
+
21
+ ---
22
+
23
+ ## Basic Script
24
+
25
+ ```python
26
+ from locust import HttpUser, task, between
27
+ import json, random
28
+
29
+ class ShopUser(HttpUser):
30
+ wait_time = between(1, 4) # Think time: 1–4 seconds (uniform random)
31
+ host = "https://api.example.com"
32
+
33
+ def on_start(self):
34
+ """Runs once per VU at startup"""
35
+ res = self.client.post("/auth/login", json={
36
+ "username": f"user{random.randint(1, 1000)}@test.com",
37
+ "password": "testpass123"
38
+ })
39
+ self.token = res.json()["access_token"]
40
+ self.client.headers.update({"Authorization": f"Bearer {self.token}"})
41
+
42
+ @task(3) # Weight: called 3x more than weight-1 tasks
43
+ def browse_products(self):
44
+ self.client.get("/products", name="GET /products")
45
+
46
+ @task(1)
47
+ def add_to_cart(self):
48
+ product_id = random.randint(1, 100)
49
+ with self.client.post(
50
+ f"/cart/items",
51
+ json={"productId": product_id, "qty": 1},
52
+ catch_response=True, # Manually handle response
53
+ name="POST /cart/items"
54
+ ) as response:
55
+ if response.status_code == 200:
56
+ response.success()
57
+ else:
58
+ response.failure(f"Expected 200, got {response.status_code}")
59
+
60
+ def on_stop(self):
61
+ self.client.post("/auth/logout")
62
+ ```
63
+
64
+ ---
65
+
66
+ ## Running Locust
67
+
68
+ ```bash
69
+ # Web UI mode
70
+ locust -f locustfile.py --host https://api.example.com
71
+
72
+ # Headless (CLI) mode
73
+ locust -f locustfile.py \
74
+ --headless \
75
+ --users 100 \
76
+ --spawn-rate 10 \
77
+ --run-time 5m \
78
+ --host https://api.example.com \
79
+ --html report.html \
80
+ --csv results
81
+
82
+ # Distributed mode
83
+ # On master:
84
+ locust -f locustfile.py --master --users 1000 --spawn-rate 50
85
+ # On each worker:
86
+ locust -f locustfile.py --worker --master-host=<master-ip>
87
+ ```
88
+
89
+ ---
90
+
91
+ ## Custom Wait Times
92
+
93
+ ```python
94
+ from locust import constant, constant_pacing, between, constant_throughput
95
+
96
+ wait_time = between(1, 5) # Uniform random 1–5s
97
+ wait_time = constant(2) # Fixed 2s
98
+ wait_time = constant_pacing(10) # Paces to 1 iteration per 10s (handles slow responses)
99
+ wait_time = constant_throughput(0.1) # Target 0.1 RPS per VU (10s average)
100
+ ```
101
+
102
+ ---
103
+
104
+ ## Custom Events and Hooks
105
+
106
+ ```python
107
+ from locust import events
108
+
109
+ @events.test_start.add_listener
110
+ def on_test_start(environment, **kwargs):
111
+ print("Test starting - seeding test data")
112
+
113
+ @events.request.add_listener
114
+ def on_request(request_type, name, response_time, response_length, exception, **kwargs):
115
+ if exception:
116
+ print(f"FAILED: {name} - {exception}")
117
+
118
+ @events.test_stop.add_listener
119
+ def on_test_stop(environment, **kwargs):
120
+ print("Test finished - cleaning up data")
121
+ ```
122
+
123
+ ---
124
+
125
+ ## Locust-Specific Tips
126
+
127
+ - Always use `name=` parameter to group parameterized URLs (e.g., `/products/123` → `name="GET /products/{id}"`).
128
+ - Use `catch_response=True` for custom validation - HTTP 200 with error body passes silently otherwise.
129
+ - Use `FastHttpUser` instead of `HttpUser` for CPU-bound or high-throughput scenarios.
130
+ - Use distributed mode above 500–1000 VUs - a single worker process saturates one CPU core.
131
+
132
+ > For anti-patterns, assertions, think time, and parameterization principles, see **Key Principles** in `SKILL.md`.
133
+ > For CI/CD integration and distributed execution details, see `../topics/test-execution.md`.