perf-skills 1.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.
@@ -0,0 +1,269 @@
1
+ # k6 Reference
2
+
3
+ > Targets: k6 v0.50+, xk6 extensions ecosystem
4
+
5
+ k6 is a developer-centric, open-source load testing tool built by Grafana Labs. Tests are written in JavaScript/TypeScript and executed with a Go runtime — making it fast, scriptable, and CI/CD-friendly.
6
+
7
+ ---
8
+
9
+ ## Core Concepts
10
+
11
+ | Concept | Description |
12
+ |---|---|
13
+ | **Virtual User (VU)** | A single simulated user executing the script |
14
+ | **Iteration** | One full execution of the default function |
15
+ | **Scenario** | Named execution profile with its own executor and config |
16
+ | **Executor** | Controls how VUs and iterations are scheduled |
17
+ | **Metric** | Built-in or custom measurement (counters, gauges, rates, trends) |
18
+ | **Check** | Inline assertion — does NOT fail the test; records pass/fail rate |
19
+ | **Threshold** | SLA definition — FAILS the test if breached |
20
+ | **Group** | Logical grouping of requests for metric aggregation |
21
+
22
+ ---
23
+
24
+ ## Script Structure
25
+
26
+ ```javascript
27
+ import http from 'k6/http';
28
+ import { check, sleep, group } from 'k6';
29
+ import { Counter, Trend } from 'k6/metrics';
30
+
31
+ // Custom metrics
32
+ const loginErrors = new Counter('login_errors');
33
+ const checkoutDuration = new Trend('checkout_duration_ms');
34
+
35
+ // Test configuration
36
+ export const options = {
37
+ scenarios: {
38
+ ramp_up: {
39
+ executor: 'ramping-vus',
40
+ startVUs: 0,
41
+ stages: [
42
+ { duration: '2m', target: 50 },
43
+ { duration: '5m', target: 50 },
44
+ { duration: '2m', target: 0 },
45
+ ],
46
+ },
47
+ },
48
+ thresholds: {
49
+ http_req_duration: ['p(95)<500', 'p(99)<1000'],
50
+ http_req_failed: ['rate<0.01'],
51
+ login_errors: ['count<5'],
52
+ },
53
+ };
54
+
55
+ // Setup (runs once before VUs start)
56
+ export function setup() {
57
+ const res = http.post('https://api.example.com/auth/token', {
58
+ client_id: 'perf-test',
59
+ client_secret: __ENV.API_SECRET,
60
+ });
61
+ return { token: res.json('access_token') };
62
+ }
63
+
64
+ // Default VU function
65
+ export default function (data) {
66
+ group('Login Flow', () => {
67
+ const res = http.post('https://api.example.com/login', JSON.stringify({
68
+ username: `user_${__VU}@example.com`,
69
+ password: 'testpass',
70
+ }), {
71
+ headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${data.token}` },
72
+ });
73
+
74
+ const ok = check(res, {
75
+ 'login status 200': (r) => r.status === 200,
76
+ 'has userId': (r) => r.json('userId') !== undefined,
77
+ });
78
+ if (!ok) loginErrors.add(1);
79
+ });
80
+
81
+ sleep(Math.random() * 3 + 1); // Think time: 1–4 seconds
82
+ }
83
+
84
+ // Teardown (runs once after all VUs finish)
85
+ export function teardown(data) {
86
+ // Cleanup, invalidate tokens, etc.
87
+ }
88
+ ```
89
+
90
+ ---
91
+
92
+ ## Executors
93
+
94
+ | Executor | Use Case | Key Options |
95
+ |---|---|---|
96
+ | `ramping-vus` | Ramp up/down | `stages: [{duration, target}]` |
97
+ | `constant-vus` | Fixed concurrency | `vus`, `duration` |
98
+ | `per-vu-iterations` | Each VU runs N times | `vus`, `iterations` |
99
+ | `shared-iterations` | Total N iterations split across VUs | `vus`, `iterations` |
100
+ | `constant-arrival-rate` | Fixed RPS (open model) | `rate`, `duration`, `preAllocatedVUs` |
101
+ | `ramping-arrival-rate` | Ramping RPS (open model) | `stages`, `preAllocatedVUs` |
102
+ | `externally-controlled` | Controlled via k6 REST API in real-time | — |
103
+
104
+ > For closed vs open model guidance and when to use each, see `references/topics/workload-design.md`.
105
+
106
+ ---
107
+
108
+ ## Checks vs Thresholds
109
+
110
+ ```javascript
111
+ // Check: logs pass/fail but does NOT fail the test
112
+ check(res, { 'status 200': (r) => r.status === 200 });
113
+
114
+ // Threshold: FAILS the test run (non-zero exit code) if breached
115
+ // Put these in options.thresholds
116
+ thresholds: {
117
+ http_req_duration: ['p(95)<500'], // p95 must be under 500ms
118
+ checks: ['rate>0.99'], // At least 99% of checks must pass
119
+ }
120
+ ```
121
+
122
+ Use thresholds for SLA enforcement in CI/CD pipelines.
123
+
124
+ ---
125
+
126
+ ## Parameterization
127
+
128
+ ### Environment variables
129
+ ```bash
130
+ k6 run -e USERNAME=testuser -e PASSWORD=secret script.js
131
+ ```
132
+ ```javascript
133
+ const username = __ENV.USERNAME;
134
+ ```
135
+
136
+ ### SharedArray (CSV / JSON data files)
137
+ ```javascript
138
+ import { SharedArray } from 'k6/data';
139
+ import papaparse from 'https://jslib.k6.io/papaparse/5.1.1/index.js';
140
+
141
+ const users = new SharedArray('users', function () {
142
+ return papaparse.parse(open('./data/users.csv'), { header: true }).data;
143
+ });
144
+
145
+ export default function () {
146
+ const user = users[__VU % users.length]; // Round-robin by VU
147
+ // use user.username, user.password
148
+ }
149
+ ```
150
+
151
+ **SharedArray loads data once and shares it across all VUs** — critical for memory efficiency at high concurrency.
152
+
153
+ ---
154
+
155
+ ## Correlation (Session Handling)
156
+
157
+ ```javascript
158
+ // Extract value from JSON response
159
+ const token = res.json('data.access_token');
160
+
161
+ // Extract from HTML (regex)
162
+ const csrfToken = res.html().find('input[name="_token"]').attr('value');
163
+
164
+ // Extract from headers
165
+ const sessionId = res.headers['Set-Cookie'].match(/JSESSIONID=([^;]+)/)[1];
166
+
167
+ // Use in next request
168
+ http.get('https://api.example.com/profile', {
169
+ headers: { 'Authorization': `Bearer ${token}` },
170
+ });
171
+ ```
172
+
173
+ ---
174
+
175
+ ## Custom Metrics
176
+
177
+ ```javascript
178
+ import { Counter, Gauge, Rate, Trend } from 'k6/metrics';
179
+
180
+ const checkoutErrors = new Counter('checkout_errors'); // cumulative count
181
+ const activeUsers = new Gauge('active_users'); // current value
182
+ const successRate = new Rate('success_rate'); // ratio
183
+ const transactionTime = new Trend('transaction_time_ms'); // distribution (p50/p95/p99)
184
+
185
+ // Usage inside default()
186
+ transactionTime.add(res.timings.duration);
187
+ successRate.add(res.status === 200);
188
+ ```
189
+
190
+ ---
191
+
192
+ ## Modules & Extensions
193
+
194
+ ### Built-in k6 modules
195
+ - `k6/http` — HTTP/1.1 and HTTP/2
196
+ - `k6/ws` — WebSocket
197
+ - `k6/grpc` — gRPC
198
+ - `k6/browser` — Browser-based testing (Chromium)
199
+ - `k6/experimental/redis` — Redis client
200
+ - `k6/crypto` — Hashing and HMAC
201
+ - `k6/encoding` — Base64
202
+
203
+ ### Popular xk6 extensions (require custom build)
204
+ - `xk6-kafka` — Kafka load testing
205
+ - `xk6-sql` — SQL database testing
206
+ - `xk6-output-prometheus-remote` — Push metrics to Prometheus
207
+
208
+ Build custom k6: `xk6 build --with github.com/grafana/xk6-kafka`
209
+
210
+ ---
211
+
212
+ ## Running k6
213
+
214
+ ```bash
215
+ # Local run
216
+ k6 run script.js
217
+
218
+ # With options override
219
+ k6 run --vus 50 --duration 5m script.js
220
+
221
+ # With env vars
222
+ k6 run -e BASE_URL=https://staging.example.com script.js
223
+
224
+ # Output to multiple sinks
225
+ k6 run --out json=results.json --out influxdb=http://localhost:8086/k6 script.js
226
+
227
+ # Cloud run (Grafana Cloud k6)
228
+ k6 cloud script.js
229
+ ```
230
+
231
+ ---
232
+
233
+ ## Output and Observability
234
+
235
+ | Output | Command |
236
+ |---|---|
237
+ | Terminal summary | Default |
238
+ | JSON | `--out json=results.json` |
239
+ | InfluxDB (Grafana stack) | `--out influxdb=http://influx:8086/k6` |
240
+ | Prometheus | `--out experimental-prometheus-rw` |
241
+ | Grafana Cloud | `k6 cloud` or `--out cloud` |
242
+ | CSV | `--out csv=results.csv` |
243
+
244
+ ### InfluxDB + Grafana Dashboard
245
+ The canonical observability stack: k6 → InfluxDB → Grafana with the official k6 Grafana dashboard (ID: 2587).
246
+
247
+ ---
248
+
249
+ ## TypeScript Support
250
+
251
+ ```bash
252
+ # Use k6 template with TypeScript
253
+ npx create-k6-app@latest --template typescript my-test
254
+ ```
255
+
256
+ Benefits: Type safety, IDE autocomplete, better refactoring for large test suites.
257
+
258
+ ---
259
+
260
+ ## k6-Specific Tips
261
+
262
+ - **Always use `SharedArray`** for data files — loading data inside `default()` causes massive per-iteration overhead.
263
+ - **Use `for` loops only for sequential steps**, not concurrency — use VUs and executors for parallel load.
264
+ - **Remove `console.log` from hot paths** — dramatically reduces throughput during load runs.
265
+ - **Use `__ENV.BASE_URL`** for environment portability — never hardcode base URLs.
266
+ - **Prefer thresholds over checks alone** — without thresholds, the test always "passes" in CI/CD.
267
+
268
+ > For CI/CD integration (GitHub Actions, GitLab CI, Jenkins), see `references/topics/test-execution.md`.
269
+ > For anti-patterns, assertions, think time, and parameterization principles, see **Key Principles** in `SKILL.md`.
@@ -0,0 +1,116 @@
1
+ # LoadRunner Reference
2
+
3
+ > Targets: OpenText LoadRunner 2024+
4
+
5
+ HP/Micro Focus LoadRunner (now OpenText LoadRunner) is the industry-standard enterprise load testing tool, especially dominant in financial services, telecom, and government.
6
+
7
+ ---
8
+
9
+ ## Core Components
10
+
11
+ | Component | Description |
12
+ |---|---|
13
+ | **VuGen** | Script recorder and editor (C-based scripting) |
14
+ | **Controller** | Orchestrates scenarios and load injection |
15
+ | **Load Generator** | Hosts running VUs |
16
+ | **Analysis** | Post-test results analysis and reporting |
17
+ | **LoadRunner Cloud** | SaaS cloud execution platform |
18
+
19
+ ---
20
+
21
+ ## VuGen Script Structure
22
+
23
+ ```c
24
+ // vuser_init: Runs once at startup
25
+ vuser_init()
26
+ {
27
+ lr_think_time(0);
28
+ web_set_user("testuser", "password", "realm");
29
+ return 0;
30
+ }
31
+
32
+ // Action: Main loop (repeated per iteration)
33
+ Action()
34
+ {
35
+ // Parameterize
36
+ lr_start_transaction("Login");
37
+ web_submit_form("login",
38
+ ITEMDATA,
39
+ "Name=username", "Value={P_USERNAME}", ENDITEM,
40
+ "Name=password", "Value={P_PASSWORD}", ENDITEM,
41
+ LAST);
42
+ lr_end_transaction("Login", LR_AUTO);
43
+
44
+ lr_think_time(3);
45
+
46
+ // Correlate session ID
47
+ web_reg_save_param_regexp(
48
+ "ParamName=SessionToken",
49
+ "RegExp=name=\"_token\" value=\"([^\"]+)\"",
50
+ "Ord=1",
51
+ LAST);
52
+ web_url("Dashboard", "URL=https://app/dashboard", LAST);
53
+
54
+ return 0;
55
+ }
56
+
57
+ // vuser_end: Runs once at teardown
58
+ vuser_end()
59
+ {
60
+ web_custom_request("Logout", "URL=https://app/logout", "Method=POST", LAST);
61
+ return 0;
62
+ }
63
+ ```
64
+
65
+ ---
66
+
67
+ ## Key Protocols
68
+
69
+ | Protocol | Use Case |
70
+ |---|---|
71
+ | Web (HTTP/HTML) | Standard web apps, REST APIs |
72
+ | Web Services | SOAP/WSDL |
73
+ | Citrix ICA | Virtual desktop (Citrix) |
74
+ | SAP GUI | SAP ERP client |
75
+ | Oracle NCA | Oracle Forms |
76
+ | TruClient | AJAX-heavy SPAs (browser-based recording) |
77
+ | JDBC | Database load testing |
78
+ | JMS | Message queue testing |
79
+ | Flex/AMF | Adobe Flex applications |
80
+
81
+ ---
82
+
83
+ ## Correlation in VuGen
84
+
85
+ ```c
86
+ // Register extraction BEFORE the request it appears in
87
+ web_reg_save_param_regexp(
88
+ "ParamName=AuthToken",
89
+ "RegExp=Bearer ([A-Za-z0-9._-]+)",
90
+ "Search=Headers",
91
+ "Ord=1",
92
+ LAST);
93
+
94
+ // Use the parameter in subsequent requests
95
+ web_add_header("Authorization", "Bearer {AuthToken}");
96
+ ```
97
+
98
+ ---
99
+
100
+ ## Controller Scenario Design
101
+
102
+ 1. **Manual Scenario** - specify VU count per script, ramp-up duration, load generator assignment.
103
+ 2. **Goal-Oriented Scenario** - Controller adjusts VUs automatically to hit a target (RPS, response time).
104
+ 3. **Percentage Mode** - define percentage of VU load for each script in a mixed workload.
105
+
106
+ ---
107
+
108
+ ## Analysis Tips
109
+
110
+ - Use **Transaction Response Time** breakdown (DNS, connect, send, wait, receive).
111
+ - Compare **Hits/sec** and **Throughput** against **Response Time** to find saturation points.
112
+ - Use **Correlation graphs** to overlay server metrics (CPU, memory) from SiteScope/Diagnostics.
113
+ - Export to Excel or integrate with LoadRunner Cloud for trend analysis across runs.
114
+
115
+ > For anti-patterns, assertions, think time, and parameterization principles, see **Key Principles** in `SKILL.md`.
116
+ > For CI/CD integration details, see `references/topics/test-execution.md`.
@@ -0,0 +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 `references/topics/test-execution.md`.
@@ -0,0 +1,61 @@
1
+ # NeoLoad Reference
2
+
3
+ > Targets: NeoLoad 2024.x+
4
+
5
+ NeoLoad is a commercial enterprise performance testing tool from Tricentis, designed for large-scale, protocol-rich testing including HTTP, SAP, Citrix, and Flex.
6
+
7
+ ---
8
+
9
+ ## Core Concepts
10
+
11
+ | Concept | Description |
12
+ |---|---|
13
+ | **Virtual User Profile** | Defines a user type and its behavior |
14
+ | **Population** | Group of VU profiles with percentage mix |
15
+ | **Scenario** | Load injection profile (ramp, constant, peak) |
16
+ | **Container** | Transaction group (like JMeter Transaction Controller) |
17
+ | **Variable Extractor** | Correlation mechanism |
18
+ | **SLA Profile** | KPI thresholds; alerts and pass/fail criteria |
19
+ | **Controller** | Orchestrates test execution |
20
+ | **Load Generator** | Injects simulated users |
21
+
22
+ ---
23
+
24
+ ## Workload Design in NeoLoad
25
+
26
+ 1. **Record** via NeoLoad browser proxy or VU recorder
27
+ 2. **Parameterize** using Variable Extractors (Regexp, XPath, JSONPath) and File Variables
28
+ 3. **Apply SLA Profile** with thresholds for response time, error rate, throughput
29
+ 4. **Design Population** mixing multiple VU profiles
30
+ 5. **Configure Scenario** with ramp-up policies and constant phase
31
+
32
+ ---
33
+
34
+ ## CLI / API Execution
35
+
36
+ ```bash
37
+ # Run from command line
38
+ NeoLoadCmd -project mytest.nlp \
39
+ -scenario "Regression_Load" \
40
+ -testResultName "CI_Run_${BUILD_NUMBER}" \
41
+ -leaseServer neoload-controller:7400
42
+
43
+ # REST API trigger (for CI/CD)
44
+ curl -X POST "https://neoload-api.tricentis.com/v3/tests/{testId}/start" \
45
+ -H "accountToken: $NEOLOAD_TOKEN" \
46
+ -d '{"scenario": "Load_Scenario"}'
47
+ ```
48
+
49
+ ---
50
+
51
+ ## NeoLoad-Specific Tips
52
+
53
+ - Always set **Network Emulation** to match target environment (LAN, WAN, mobile).
54
+ - Use **Shared Containers** for reusable sequences (e.g., authentication flow).
55
+ - Configure **Cache and Cookie Policies** per application behavior.
56
+ - Use **NeoLoad Web** for centralized result storage, trend analysis, and team collaboration.
57
+ - Integrate with **Dynatrace/AppDynamics** via built-in APM connectors.
58
+ - Use **as-code YAML definitions** (NeoLoad as Code) for version-controlled test configs.
59
+
60
+ > For anti-patterns, assertions, think time, and parameterization principles, see **Key Principles** in `SKILL.md`.
61
+ > For CI/CD integration details, see `references/topics/test-execution.md`.
@@ -0,0 +1,50 @@
1
+ # OctoPerf Reference
2
+
3
+ > Targets: OctoPerf SaaS (current)
4
+
5
+ OctoPerf is a cloud-based SaaS performance testing platform built on top of JMeter. It provides a professional UI for test design, cloud execution, and centralized result management.
6
+
7
+ ---
8
+
9
+ ## Key Capabilities
10
+
11
+ | Feature | Description |
12
+ |---|---|
13
+ | **JMeter import/export** | Import existing `.jmx` files; export OctoPerf designs as JMeter |
14
+ | **Visual scenario builder** | GUI for scripting without raw JMeter XML editing |
15
+ | **Cloud execution** | On-demand cloud load generators (AWS regions) |
16
+ | **Real-time dashboards** | Live metrics during test run |
17
+ | **Trend analysis** | Compare runs over time |
18
+ | **SLA alerts** | Email/Slack notifications on KPI breach |
19
+
20
+ ---
21
+
22
+ ## Workflow
23
+
24
+ 1. **Import or Record** - upload existing JMX or use OctoPerf's HAR import (record browser -> export HAR -> import).
25
+ 2. **Parameterize** - use OctoPerf variable extractors (JSON, Regexp, Header) in the GUI.
26
+ 3. **Configure Load Profile** - ramp-up wizard or custom curve editor.
27
+ 4. **Select Regions** - pick cloud injection regions (US-East, EU-West, APAC, etc.).
28
+ 5. **Run and Monitor** - real-time dashboard with RPS, response time percentiles, error rate.
29
+ 6. **Analyze** - use built-in report builder or export to CSV/JSON.
30
+
31
+ ---
32
+
33
+ ## OctoPerf-Specific Tips
34
+
35
+ - Use OctoPerf's **HAR importer** to quickly create scripts from browser recordings.
36
+ - Leverage **Virtual User Groups** to model different user populations.
37
+ - Store test plans in **Workspaces** with version history.
38
+ - Use the **REST API** to trigger runs from CI/CD:
39
+
40
+ ```bash
41
+ # Trigger run via API
42
+ curl -X POST "https://api.octoperf.com/analysis/executions" \
43
+ -H "X-Api-Key: $OCTOPERF_API_KEY" \
44
+ -d '{"scenarioId": "abc123", "name": "CI Build #42"}'
45
+ ```
46
+
47
+ - Always set **SLA thresholds** in the test profile so CI gates work reliably.
48
+
49
+ > For anti-patterns, assertions, think time, and parameterization principles, see **Key Principles** in `SKILL.md`.
50
+ > For CI/CD integration details, see `references/topics/test-execution.md`.