You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/index.md
+203Lines changed: 203 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -246,6 +246,209 @@ The factory handles worker coordination automatically:
246
246
3.**Last Worker**: Executes `on_last_worker` callback during teardown
247
247
4.**Cleanup**: Last worker removes all temporary files
248
248
249
+
## Rate Limiting
250
+
251
+
The plugin provides a [`rate_limiter_fixture_factory`](../src/pytest_load_testing/concurrent_fixtures.py:305) for enforcing rate limits across pytest-xdist workers. This is essential for load testing scenarios where you need to respect API rate limits or simulate realistic traffic patterns.
252
+
253
+
### Overview
254
+
255
+
The rate limiter uses the **token bucket algorithm**, which allows controlled bursts of activity while maintaining an average rate over time. State is synchronized across all workers using file-based locking.
256
+
257
+
### Basic Usage
258
+
259
+
```python
260
+
import pytest
261
+
from pytest_load_testing import weight
262
+
from pytest_load_testing.token_bucket_rate_limiter import RateLimit
263
+
264
+
@pytest.fixture(scope="session")
265
+
defapi_limiter(rate_limiter_fixture_factory):
266
+
"""Rate limiter for API calls."""
267
+
return rate_limiter_fixture_factory(
268
+
name="api_limiter",
269
+
hourly_rate=RateLimit.per_second(10) # 10 calls per second
270
+
)
271
+
272
+
@weight(1)
273
+
deftest_api_call(api_limiter):
274
+
with api_limiter.rate_limited_context() as ctx:
275
+
# Context entry waits if rate limit would be exceeded
276
+
response = api.get("/data")
277
+
assert response.status_code ==200
278
+
assert ctx.call_count >=1
279
+
```
280
+
281
+
### Rate Limit Helpers
282
+
283
+
The `RateLimit` class provides convenient factory methods:
284
+
285
+
```python
286
+
RateLimit.per_second(10) # 10 calls per second (36,000/hour)
287
+
RateLimit.per_minute(600) # 600 calls per minute (36,000/hour)
288
+
RateLimit.per_hour(3600) # 3600 calls per hour
289
+
RateLimit.per_day(86400) # 86400 calls per day (3,600/hour)
-**Waits** if necessary to respect the rate limit before entering
432
+
-**Tracks** call count, exceptions, and timing
433
+
-**Yields** a progress object with attributes:
434
+
-`id`: The limiter name
435
+
-`call_count`: Total calls made
436
+
-`exceptions`: Total exceptions encountered
437
+
-`start_time`: When rate limiting started (timestamp)
438
+
-`hourly_rate`: Current rate limit in calls per hour
439
+
440
+
```python
441
+
with api_limiter.rate_limited_context() as ctx:
442
+
print(f"Limiter: {ctx.id}")
443
+
print(f"Call count: {ctx.call_count}")
444
+
print(f"Rate: {ctx.hourly_rate} calls/hour")
445
+
# Make your API call here
446
+
```
447
+
448
+
### Thread Safety
449
+
450
+
All rate limiter state is synchronized across workers using file-based locking via `SharedJson`. Multiple workers can safely share the same rate limiter instance without race conditions.
0 commit comments