A Python-scriptable load testing tool (Go binary wrapper)
Project description
Sthenos
Sthenos is a modern, high-performance load testing tool written in Go. It combines the raw power of Go with the simplicity of Python-like scripting (Starlark) for an effortless developer experience.
Features
- High Performance: Built on Go, using lightweight goroutines for Virtual Users (VUs).
- Python-like Scripting: Write test scripts in Starlark (a dialect of Python).
- CLI Driven: Simple, powerful command-line interface.
- Metrics: Detailed breakdown of HTTP request lifecycle (DNS, TLS, TTFB, etc.).
- Thresholds: Define pass/fail criteria directly in your script.
- Stages: Ramp up/down VUs to simulate real-world traffic patterns.
- Zero-Dependency Installation:
pip install sthenosworks instantly (bundles pre-compiled binaries). - K6 Compatibility: Supports Stages, Checks, Thresholds, and Setup/Teardown lifecycles.
- Detailed Metrics: Breakdown of DNS, TLS, TTFB, and more.
Installation
Via PyPI (Recommended)
pip install sthenos
From Source
git clone https://github.com/richard24se/Sthenos.git
cd Sthenos/sthenos
go build -o sthenos main.go
Usage
Basic Run
./sthenos run script.py
Options
Override script defaults via CLI flags:
./sthenos run \
--vus 10 \
--duration 30s \
--out json=results.json \
--env HOST=api.staging.com \
script.py
| Flag | Description | Default |
|---|---|---|
--vus |
Number of Virtual Users | 1 |
--duration |
Test duration (e.g., 10s, 1m) |
10s |
--env |
Set environment variable (KEY=VAL) |
- |
--out |
Output format (currently json=path) |
- |
--graceful-stop |
Timeout to wait for active VUs | 30s |
--verbose |
Show detailed timing breakdown | false |
Examples & Features
Sthenos scripting is designed to be intuitive. Below are examples covering all major features. Scripts are written in Starlark, which looks and feels like Python.
1. Basic Request (01_basic.py)
The simplest test—hitting an endpoint repeatedly.
# Command: sthenos run --vus 5 --duration 5s examples/01_basic.py
# 01_basic.py: Minimal load test
from sthenos import http, sleep
def default():
# Perform a simple GET request
http.get("http://localhost:9001/")
sleep(0.2)
sleep(1)
2. Traffic Stages (02_stages.py)
Simulate ramping up and down traffic patterns.
# Command: sthenos run examples/02_stages.py
# 02_stages.py: Ramping VUs using stages
from sthenos import http, sleep
# Define ramping stages
options = {
"stages": [
{"duration": "2s", "target": 5}, # Ramp up to 5 VUs
{"duration": "5s", "target": 10}, # Stay at 5 VUs
{"duration": "2s", "target": 0}, # Ramp down to 0
]
}
def default():
http.get("http://localhost:9001/")
sleep(0.5)
3. Fail/Pass Criteria (03_thresholds.py)
Ensure your system meets specific SLIs. The test exits with code 1 if thresholds fail.
# Command: sthenos run examples/03_thresholds.py
# 03_thresholds.py: Defining Pass/Fail criteria
from sthenos import http, check, sleep
options = {
# Thresholds allow CI/CD integration
"thresholds": {
"http_req_duration": ["p(95) < 500"], # 95% of requests must be faster than 500ms
"checks": ["rate > 0.95"], # 95% of checks must pass
"http_req_failed": ["rate < 0.01"], # Less than 1% errors
},
"stages": [
{"duration": "5s", "target": 100},
]
}
def default(ctx):
res = http.get("http://localhost:9001/")
# This check feeds the "checks" metric
check(res, {
"is status 200": lambda r: r.status == 200,
})
sleep(1)
4. Validating Responses (04_env_vars.py)
This example shows how to use environment variables.
# Command: sthenos run --env HOST=https://httpbin.org --env USER=admin examples/04_env_vars.py
# 04_env_vars.py: Using Environment Variables
from sthenos import http, check, sleep, ENV
def setup():
# Access injected env vars via global ENV dict
host = ENV.get("HOST", "http://localhost:9001")
user = ENV.get("USER", "guest")
print("[Setup] Target: {host}, User: {user}".format(host=host, user=user))
return {"host": host}
def default(ctx):
url = "{host}/".format(host=ctx["host"])
http.get(url)
sleep(1)
5. POST JSON Data (05_post_json.py)
Send JSON payloads easily.
# Command: sthenos run --vus 2 --duration 5s examples/05_post_json.py
# 05_post_json.py: Sending POST requests
from sthenos import http, check, sleep
def default(ctx):
# TODO: Current MVP implementation supports basic POST
# Future: support full JSON body as dict
payload = '{"foo": "bar"}'
res = http.post("http://localhost:9001/post", payload)
check(res, {
"status is 200": lambda r: r.status == 200,
})
sleep(0.1)
6. Environment Variables (06_checks.py)
This example shows how to use checks to validate responses.
# Command: sthenos run --vus 5 --duration 5s examples/06_checks.py
# 06_checks.py: Validating responses
from sthenos import http, check, sleep
def default(ctx):
res = http.get("http://localhost:9001/get")
# Checks don't stop execution but are recorded
success = check(res, {
"status is 200": lambda r: r.status == 200,
"body size > 0": lambda r: len(r.body) > 0,
})
if not success:
print("Request failed validation!")
sleep(1)
7. Full Lifecycle (07_lifecycle.py)
Use setup() (once globally) to prepare data, and teardown() (once globally) to clean up.
# Command: sthenos run examples/07_lifecycle.py
# 07_lifecycle.py: Demonstrating the full test lifecycle
# Init -> Setup(once) -> VU(many) -> Teardown(once)
from sthenos import http, check, sleep
# 1. INIT PHASE
# Executed once per VU process/thread
print("[Phase] Init")
# 2. SETUP PHASE
# Executed once globally. Returns 'ctx' data.
def setup():
print("[Phase] Setup: Generating Test Data...")
return {"token": "secret_abc_123", "items": [1, 2, 3]}
# 3. VU PHASE
# Executed repeatedly. Receives 'ctx'.
def default(ctx):
# print("[Phase] VU: Using token {}".format(token)) # Uncomment to see per-VU logs
# Simulate work
res = http.get("http://localhost:9001/headers", {"headers": {"Authorization": ctx["token"]}})
# Validate that server received the token via Response Headers
check(
res,
{
"status is 200": lambda r: r.status == 200,
},
)
check(
res,
{
"token verified": lambda r: r.headers.get("X-Token-Received") == ctx["token"],
},
)
sleep(0.5)
# 4. TEARDOWN PHASE
# Executed once globally. Receives 'ctx'.
def teardown(ctx):
print("[Phase] Teardown: Data {} clean up complete.".format(ctx["items"]))
8. Complete Scenario (08_ecommerce.py)
Combine everything to simulate a real user journey.
# Command: sthenos run examples/08_ecommerce.py
# 08_ecommerce.py: User Journey Simulation
# Features: Stages, Thresholds, Env Vars, Setup, Checks, Sleep, POST
from sthenos import http, check, sleep, ENV
# 1. Option Configuration
options = {
# Ramping Load Pattern
"stages": [
{"duration": "10s", "target": 50}, # Ramp up to 5 users
{"duration": "5s", "target": 5}, # Stay at 5 users
{"duration": "2s", "target": 0}, # Ramp down to 0
],
# Pass/Fail Criteria
"thresholds": {
"http_req_duration": ["p(95)<500"], # 95% of requests must be faster than 500ms
"checks": ["rate>0.95"], # 95% of checks must pass
"http_req_failed": ["rate<0.01"], # Less than 1% failure
},
}
# 2. Setup Phase
def setup():
# Use Environment Variable for dynamic targeting
# usage: sthenos run --env HOST=https://my-api.com examples/08_ecommerce.py
# usage: sthenos run --env HOST=https://my-api.com examples/08_ecommerce.py
host = ENV.get("HOST", "http://localhost:9001")
print("Setup: Targeting {}".format(host))
return {"host": host}
# 3. VU Logic
def default(ctx):
host = ctx["host"]
# Step 1: Browse Home Page
res = http.get("{}/get?page=home".format(host))
check(res, {
"home status 200": lambda r: r.status == 200,
})
sleep(1.0) # User thinks
# Step 2: View Product
res = http.get("{}/get?product=123".format(host))
check(res, {
"product status 200": lambda r: r.status == 200,
})
sleep(0.5)
# Step 3: Add to Cart (POST)
# Note: Sthenos supports string body for POST
payload = '{"product_id": 123, "qty": 1}'
params = {
"headers": {
"Content-Type": "application/json",
"Authorization": "Bearer secret_token",
}
}
res = http.post("{}/post".format(host), payload, params)
check(res, {
"cart add status 200": lambda r: r.status == 200,
})
sleep(1.0)
def teardown(data):
print("Teardown: Test Complete.")
Metrics Output
Sthenos produces a k6-inspired summary to the console:
_____ _______ _ _ ______ _ _ ____ _____
/ ____|__ __| | | | ____| \ | |/ __ \ / ____|
| (___ | | | |__| | |__ | \| | | | | (___
\___ \ | | | __ | __| | . | | | |\___ \
____) | | | | | | | |____| |\ | |__| |____) |
|_____/ |_| |_| |_|______|_| \_|\____/|_____/
Initial VUs: 100, Duration: 5s
Running Setup...
Setup: Targeting http://localhost:9001
Mode: Forced Constant (CLI Overrides). VUs: 100, Duration: 5s
Starting Constant Load: 100 VUs for 5s
running [=========================] 5s / 5s
Stopping VUs and waiting for graceful exit...
Running Teardown...
Teardown: Test Complete.
✓ checks...........................: 100.00% ✓ 600 / 600
data_received......................: 118.4 kB 23.2 kB/s
data_sent..........................: 49.4 kB 9.7 kB/s
http_req_duration..................: avg=10.67ms min=0.00ms med=1.06ms max=85.21ms p(90)=44.67ms p(95)=65.27ms
http_reqs..........................: 600 117.47/s
http_req_failed....................: 0 0.00%
vus................................: 100 min=100 max=100
vus_max............................: 100 min=100 max=100
--- Thresholds ---
http_req_duration p(95)<500 ... PASS
checks rate>0.95 ... PASS
http_req_failed rate<0.01 ... PASS
------------------
Comparisons
| Feature | k6 (OSS) | Sthenos |
|---|---|---|
| Language | Go | Go |
| Scripting | JavaScript (ES6) | Starlark (Python dialect) |
| Engine | goja | go.starlark.net |
| Concurrency | Goroutines | Goroutines |
| Ecosystem | Mature | Experimental |
License
STHENOS LICENSE
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sthenos-0.1.1.tar.gz.
File metadata
- Download URL: sthenos-0.1.1.tar.gz
- Upload date:
- Size: 14.8 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
460dc5eb310fff8a9e1c2850938d5067cf1553ec596c34098f8d5709a0f1a781
|
|
| MD5 |
f7cccdf4e8abce43856543860e4894f4
|
|
| BLAKE2b-256 |
6cae99487bfd3659f23f1c0d3ead708bf7403acb44b3747e0e613b9d7b21af67
|
File details
Details for the file sthenos-0.1.1-py3-none-any.whl.
File metadata
- Download URL: sthenos-0.1.1-py3-none-any.whl
- Upload date:
- Size: 14.9 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e11fe12d8006b62ff79e8371e6fc6417c4211b3e7f18a7c930b656fafbfb6efa
|
|
| MD5 |
d7fb9b1cb45b7f2029950271ffee1c16
|
|
| BLAKE2b-256 |
44c4a08eafc6948e9228024ecd549852ab0224be2abac23da4d59cdc4fccfb62
|