Web UI
The control plane serves a built-in web UI at its public URL (default http://localhost:8080 after Docker Compose). You can run the full load-test loop from the browser — no YAML required.
make quickstartmake docker-open # or: test-scale open# Open the UI URL printed at the end of quickstartThe header shows the deployment mode (Docker / Kubernetes / Ingress), the public URL, and the build version.
Authentication
Section titled “Authentication”If TEST_SCALE_API_KEY is set on the control plane (Compose sets a local key), protected API calls prompt for the key once. The UI stores it in sessionStorage as X-Test-Scale-Key for later requests.
With Docker Compose, make docker-open / make docker-run already use the key from deploy/docker/scripts/ports.sh. If the prompt appears, paste the same value (local-dev-key in the default Compose stack, or whatever your .ports.env / Helm notes print).
Tabs overview
Section titled “Tabs overview”| Tab | Purpose |
|---|---|
| Submit | Create a plan (or reuse a saved one) and start a run |
| Runs | Live table of recent runs — stop, re-run, open Grafana |
| Compare | Diff two completed runs (RPS, latency, errors, cost) |
| Dashboard | Embedded Grafana view for a selected run |
Submit — start a run
Section titled “Submit — start a run”- Choose New configuration or Saved plan.
- Fill the form (or pick a saved plan to re-run its stored request).
- Click Start Run.
Form fields
Section titled “Form fields”| Field | Notes |
|---|---|
| Plan / run name | Optional labels for history |
| Target URL | In Docker, use http://mock-target or http://host.docker.internal:<port> — not localhost for host apps |
| Target RPS / duration | Aggregate RPS and load duration |
| Ramp pattern | constant, ramp, step, spike |
| HTTP method / timeout | Defaults to GET / 10000 ms |
| Auth | None, Bearer/JWT, session cookie, or custom header |
| Extra headers | JSON object, e.g. {"X-Request-Id":"load-test"} |
| Body / JSON payload | Raw body text; UI sends it as the request body |
| Expected statuses | Comma-separated; empty means any 2xx |
| SLO (optional) | p95 latency (ms) and max error rate |
A cost estimate card updates as you change RPS and duration (worker count × configured rate).
Target verification (when enabled)
Section titled “Target verification (when enabled)”If the control plane requires ownership checks (SAFETY_VERIFICATION_TOKEN):
localhost/127.0.0.1targets skip verification.- Remote targets must serve the token at
{target_url}/.well-known/test-scale-verification
Use Check target before starting.
Runs — history and actions
Section titled “Runs — history and actions”The Runs tab auto-refreshes. Each row shows status, slug, target, RPS, p95, errors, SLO, and cost.
Typical actions (per row, depending on state):
- Stop a running test
- Re-run a completed plan
- Open the dashboard for that run’s Grafana view
Slugs look like run-0708-0843-b2ab — use the same IDs with the CLI.
Compare — regression check
Section titled “Compare — regression check”- Select a current run and a baseline (same target and load config).
- Click Compare.
The UI shows metric deltas (throughput, percentiles, errors, cost) and highlights regressions. For CI gates, use:
test-scale diff -c <current-slug> -b <baseline-slug> --fail-on-regressionDashboard — Grafana embed
Section titled “Dashboard — Grafana embed”The Dashboard tab embeds Grafana for the selected run. Pick a run from the dropdown and Refresh if panels look stale.
| Deployment | Where Grafana comes from |
|---|---|
| Docker Compose | Separate Grafana port (printed by quickstart, often :3001) and/or in-UI embed via GRAFANA_BASE_URL |
| Ingress | Often /grafana on the same host |
| Port-forward K8s | Forward Grafana service or use the URL configured in Helm values |
Docker vs Kubernetes UX notes
Section titled “Docker vs Kubernetes UX notes”The UI adapts messaging to the deployment mode:
- Docker — reminds you that workers are containers; use
host.docker.internalfor apps on your laptop. - Kubernetes (port-forward) — workers scale via KEDA in the cluster.
- Ingress + TLS — dashboards may load from
/grafanaon the same host.
UI vs CLI vs YAML
Section titled “UI vs CLI vs YAML”| Task | Best tool |
|---|---|
| Exploratory runs, demos | Web UI |
Secrets in plans (${ENV_VAR}) |
CLI + YAML — expansion happens when the CLI parses the file |
| CI gates / scripting | CLI (--json, --fail-on-regression) |
| Re-run exact saved plan | UI Saved plan or test-scale rerun |
Plans and runs created in the UI use the same REST API as the CLI. Environment-variable expansion for secrets is CLI/file only — paste tokens into the UI auth fields for interactive runs, or submit YAML via the CLI.
Open the UI
Section titled “Open the UI”make docker-open# ortest-scale opentest-scale open --print # print URL onlyKubernetes without Ingress:
kubectl port-forward -n test-scale svc/test-scale-ctrl-plane 8080:8080open http://localhost:8080Related
Section titled “Related”- First run — get a UI URL from
make quickstart - Test plans — full YAML field reference
- CLI — scripting and watch mode
- Interpreting results — when to trust the numbers