Self-contained benchmark for running a realistic WooCommerce admin workflow with k6 and exporting results to CSV.
No Grafana, InfluxDB, or other observability stack is required.
Licensed under the MIT License.
Before running CPU comparisons, configure your site to emit X-PHP-Runtime-Ms (or the header name in .env). See README-TEST.md section "PHP runtime header setup" for setup and verification.
Default flow (state-safe: only disposable benchmark entities are created or mutated):
| Bundle | Steps | Notes |
|---|---|---|
| Auth | A1–A4 | Login, dashboard, logout |
| Analytics | R1 | WooCommerce admin home |
| Orders | O1–O4, O7 | List, filter, optional search, create order, add note |
| Coupons | C1–C4 | List, optional search, create/update disposable coupon |
| Customers | U1–U5 | List, optional search, create/update disposable customer |
| Catalog | P1, P6 | Product list + create draft; P3 search if configured; P4/P5 only if WP_ADMIN_PRODUCT_ID is set |
| Cleanup | X1–X4 | Remove entities created in the run |
Optional steps (env-driven): O3, O5 (fixture order), C2, U2, P3, P4, P5.
See README-TEST.md for the full step catalog and URL patterns.
- Docker with Compose v2
- A WordPress + WooCommerce site reachable from the machine running Docker
- Your IP allowlisted if the host restricts admin access
git clone https://github.com/pressidium/wordpress-cpu-benchmark.git
cd wordpress-cpu-benchmark
cp .env.example .env
make pullUse your fork or mirror URL if you did not clone from the repository above.
Pull the pinned k6 image (grafana/k6:0.57.0 in docker-compose.yml) before the first run, and again after upgrading the pin.
Edit .env: set DOMAIN, WP_ADMIN_USER, WP_ADMIN_PASSWORD, and STACK_LABEL (for example a CPU / hosting tier label).
Single run:
make run-adminMultiple full-flow iterations (2s pause between iterations by default):
make run-admin RUNS=10CSV output:
results/<TEST_ID>.csv
If TEST_ID is unset, a timestamped id is generated automatically.
If results/<TEST_ID>.csv already exists, the script appends the current timestamp to the id (for example wp-admin-lon-2-shared-20260529-130000.csv) so previous results are not overwritten.
Do not commit .env or results/*.csv. Both are listed in .gitignore.
Use php_runtime_ms per sampler (admin step name) for server-side PHP comparison. See README-TEST.md for tag semantics and pacing notes.
Do not use gaps between CSV timestamp values as request latency — timestamps are 1-second buckets and include fixed k6 pacing between steps (2s in dev mode).
Filter in a spreadsheet:
metric_name == php_runtime_ms- Group/compare by
samplerandstack(fromSTACK_LABEL)
scripts/collect-site-brief.sh runs on the WordPress server with WP-CLI. It is not executed through Docker Compose.
Copy the script to the server (or run it from a checkout there), then collect output:
# From your laptop
scp scripts/collect-site-brief.sh user@your-server:/tmp/
ssh user@your-server \
'WP_PATH=/var/www/html bash /tmp/collect-site-brief.sh' \
| tee site-brief-$(date +%Y%m%d).txt
# Or directly on the server, from the repository root
WP_PATH=/var/www/html ./scripts/collect-site-brief.sh | tee site-brief-$(date +%Y%m%d).txtSee usage in the header comment of scripts/collect-site-brief.sh.
See .env.example for a minimal template. URLs are built from DOMAIN only (TARGET_URL is not used).
| Variable | Purpose |
|---|---|
DOMAIN |
Site hostname (no scheme), e.g. example.com |
WP_ADMIN_USER |
WordPress admin username |
WP_ADMIN_PASSWORD |
WordPress admin password |
| Variable | Default | Purpose |
|---|---|---|
TEST_ID |
auto | Run id (CSV filename + testid tag) |
STACK_LABEL |
unset | Label for stack variant, e.g. lon2-shared |
K6_DEV_MODE |
true |
Single VU, sequential iterations |
WP_ADMIN_RUN_ITERATIONS |
1 |
Full admin-flow repetitions per run |
WP_ADMIN_ITERATION_SLEEP_SEC |
2 |
Pause between full iterations |
WP_ADMIN_MAX_DURATION |
auto | k6 scenario cap (e.g. 180m for 50 iterations) |
WP_ADMIN_SLEEP_MIN / WP_ADMIN_SLEEP_MAX |
0 / 0 |
Random per-step sleep when K6_DEV_MODE=false (code fallback: 5–10s if unset) |
WP_ADMIN_FETCH_ASSETS |
false |
Skip static asset fetches |
WP_ADMIN_PHP_RUNTIME_HEADER_ENABLED |
true |
Record php_runtime_ms from response header |
WP_ADMIN_PHP_RUNTIME_HEADER_NAME |
X-PHP-Runtime-Ms |
Header name to parse |
When K6_DEV_MODE=true, the script uses a fixed 2 second pause between admin steps (humanSleep()). WP_ADMIN_SLEEP_MIN / WP_ADMIN_SLEEP_MAX are ignored in that mode.
Long runs: with 50 iterations, allow roughly 130–180 minutes (WP_ADMIN_MAX_DURATION is auto-estimated if unset).
| Variable | Default | Purpose |
|---|---|---|
WP_LOGIN_PATH |
wp-login.php |
Login path |
WP_LOGIN_EXTRA_PARAM |
aio_special_field |
POST field name for hide-login plugins |
WP_LOGIN_EXTRA_FIELD |
unset | Value sent in that POST field when login requires an extra token |
WP_ADMIN_BUNDLES |
all |
Subset of bundles to run |
WP_ADMIN_ORDER_CREATE |
true |
Create disposable order |
WP_ADMIN_COUPON_CREATE |
true |
Create disposable coupon |
WP_ADMIN_CUSTOMER_CREATE |
true |
Create disposable customer |
WP_ADMIN_PRODUCT_CREATE |
true |
Create disposable product draft |
WP_ADMIN_CLEANUP |
true |
Run cleanup after actions |
WP_ORDER_SEARCH_QUERY |
unset | Enable O3 order search |
WP_PRODUCT_SEARCH_QUERY |
unset | Enable P3 product search |
WP_COUPON_SEARCH_QUERY |
unset | Enable C2 coupon search |
WP_CUSTOMER_SEARCH_QUERY |
unset | Enable U2 customer search |
Fixture IDs and save toggles are documented in .env.example.
Use this when you want every optional URL pattern without mutating existing site data (only DOMAIN, credentials, and STACK_LABEL required beyond defaults):
WP_ORDER_SEARCH_QUERY=1
WP_PRODUCT_SEARCH_QUERY=k6
WP_COUPON_SEARCH_QUERY=k6
WP_CUSTOMER_SEARCH_QUERY=k6
WP_ADMIN_PRODUCT_CAT=uncategorizedAll create/cleanup flags default to enabled in .env.example.
.
LICENSE
Makefile
docker-compose.yml
.env.example
README.md
README-TEST.md
scripts/
run-admin.sh
collect-site-brief.sh
tests/
examples/wp-admin-flow.test.js
lib/
smoke/
results/ # generated CSV output (gitignored; .gitkeep only)
Pull images first if you have not run make pull:
make pull
make smokeParser/helper smoke test (no live site or credentials required).
README-TEST.md— step catalog, URL patterns, PHP header setup, pacing, writing new tests