@cloudbeat/atlas-cli 0.3.0 → 0.4.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.
Files changed (41) hide show
  1. package/README.md +46 -19
  2. package/dist/api.js +20 -0
  3. package/dist/cli.js +34 -6
  4. package/dist/commands/analyze.js +118 -0
  5. package/dist/commands/capacity.js +99 -0
  6. package/dist/commands/docs.js +57 -0
  7. package/dist/commands/files.js +18 -4
  8. package/dist/commands/plan.js +100 -0
  9. package/dist/commands/record.js +11 -1
  10. package/dist/commands/results.js +13 -7
  11. package/dist/commands/schema.js +86 -0
  12. package/dist/commands/skills.js +111 -0
  13. package/dist/commands/tests.js +73 -0
  14. package/dist/docs/agent-setup.md +109 -0
  15. package/dist/docs/agent-tasks.md +169 -0
  16. package/dist/docs/ai-agents.md +90 -0
  17. package/dist/docs/auth.md +74 -0
  18. package/dist/docs/automation.md +150 -0
  19. package/dist/docs/ci.md +105 -0
  20. package/dist/docs/clusters.md +48 -0
  21. package/dist/docs/commands.md +155 -0
  22. package/dist/docs/files.md +86 -0
  23. package/dist/docs/generators.md +52 -0
  24. package/dist/docs/getting-started.md +85 -0
  25. package/dist/docs/index.json +110 -0
  26. package/dist/docs/projects.md +50 -0
  27. package/dist/docs/recorder.md +143 -0
  28. package/dist/docs/results.md +79 -0
  29. package/dist/docs/running.md +80 -0
  30. package/dist/docs/skills.md +88 -0
  31. package/dist/docs/test-plans.md +92 -0
  32. package/dist/docs/troubleshooting.md +79 -0
  33. package/dist/plan.js +250 -0
  34. package/dist/skills/AGENTS.md +70 -0
  35. package/dist/skills/atlas-analyze/SKILL.md +104 -0
  36. package/dist/skills/atlas-correlate/SKILL.md +89 -0
  37. package/dist/skills/atlas-load-test/SKILL.md +154 -0
  38. package/dist/skills/atlas-record/SKILL.md +167 -0
  39. package/dist/skills/atlas-run/SKILL.md +109 -0
  40. package/dist/skills/atlas-test-plan/SKILL.md +281 -0
  41. package/package.json +5 -3
@@ -0,0 +1,281 @@
1
+ ---
2
+ name: atlas-test-plan
3
+ description: Get a test plan and its data files into an Atlas project - download an existing plan, edit it or add a scenario to it, turn a fresh recording into a real test, put repeated values into a data file, debug it locally, check it will actually run, and upload it back. Use when someone wants to change an existing test, add a flow to one, asks what to do next with a plan or a recording they just made, fix a plan that reports nothing, or manage a project's test data files.
4
+ ---
5
+
6
+ # Test plans and data files
7
+
8
+ Every test needs a plan (`.jmx`) and usually data files (`.csv`/`.txt`) in the
9
+ project. There are two ways to arrive at one, and both end the same way: check
10
+ it, upload it, smoke-run it.
11
+
12
+ **Start by looking at what is already there:**
13
+
14
+ ```bash
15
+ atlas files list -p <project> --json
16
+ ```
17
+
18
+ ## Path A — change an existing plan
19
+
20
+ ```bash
21
+ atlas files download -p <project> checkout.jmx -o ./checkout.jmx
22
+ ```
23
+
24
+ Downloading first is not optional: **uploading replaces a file of the same name**
25
+ and there is no version history. The copy you downloaded is the only way back.
26
+
27
+ Then edit. Three kinds of change, in order of preference:
28
+
29
+ **Add a whole new scenario** — record it straight into the downloaded plan. An
30
+ existing target file is merged into, not overwritten, so the new flow arrives as
31
+ an additional thread group and a `.bak` is written first:
32
+
33
+ ```bash
34
+ atlas-rec start https://shop.example.com -o ./checkout.jmx -n "New checkout"
35
+ # ... drive it, see atlas-record ...
36
+ atlas-rec stop
37
+ ```
38
+
39
+ **Change values in place** — thread counts, a data-file name, a host. Edit the
40
+ specific `<stringProp>` and nothing else:
41
+
42
+ ```xml
43
+ <stringProp name="ThreadGroup.num_threads">50</stringProp>
44
+ <stringProp name="filename">users.csv</stringProp>
45
+ ```
46
+
47
+ Never reformat the file, and never add or remove an element by hand unless you
48
+ are certain about its `<hashTree>`. Every element in a JMeter plan is followed by
49
+ a `<hashTree>` holding its children; an unbalanced one means JMeter will not open
50
+ the file at all. `atlas plan check` counts them for you.
51
+
52
+ **Structural surgery** — new controllers, reordering, deleting a thread group.
53
+ Say plainly that this is better done in the JMeter GUI, and offer the targeted
54
+ alternative instead. Replacing a plan you do not fully understand is how someone
55
+ loses a scenario nobody has the source for.
56
+
57
+ ## Path B — a new plan
58
+
59
+ Record one (see `atlas-record`), which produces a plan whose thread counts can be
60
+ set at run time. Then continue below.
61
+
62
+ ## Turning a recording into a test
63
+
64
+ A freshly recorded plan is a draft. Someone arriving with one — "I recorded a
65
+ flow, what next?" — needs these stages, in this order, **asking as you go rather
66
+ than deciding for them**. Do not upload it, and do not start editing it, before
67
+ they have answered.
68
+
69
+ Start by saying what is there: the scenario name, each transaction with its
70
+ request count, any unexpected status codes, and where the plan and capture files
71
+ are.
72
+
73
+ **1. Is the flow right?** Are the steps and their names the ones they want
74
+ reported? A missing step means recording again; a bad name is a one-line fix.
75
+
76
+ **2. Should the recorded values become test data?** This is the question that
77
+ turns a recording into a load test, so raise it every time. Read the capture and
78
+ list what each simulated user would otherwise send identically:
79
+
80
+ ```bash
81
+ atlas-rec state --full # while recording
82
+ atlas-rec inspect flow.capture.json
83
+ ```
84
+
85
+ Look through the request parameters and bodies for:
86
+
87
+ - **Credentials** — a username and password typed during the recording. Every
88
+ user signing in as one person is the most common way a test measures nothing
89
+ real: sessions collide, caches hide the work, and the login step is not tested
90
+ at all.
91
+ - **Search terms, product ids, categories, postcodes** — one value means one
92
+ cached answer, repeated.
93
+ - **Quantities, dates, addresses** — anything a real user varies.
94
+
95
+ Distinguish these from **values the server issued** — session ids, tokens,
96
+ cart ids, anything that came back in an earlier response. Those are correlation,
97
+ not test data, and belong to `atlas-correlate`. `atlas-rec suggest` finds them.
98
+
99
+ Propose a data file for the rest: say which values you would parameterise, what
100
+ you would call the columns, and how many rows they need. Ask whether they have
101
+ real data to use or want you to generate it — realistic data is theirs to
102
+ provide, and generated data is fine when they say so.
103
+
104
+ ```csv
105
+ username,password,search_term
106
+ user001,...,laptop
107
+ user002,...,headphones
108
+ ```
109
+
110
+ Then wire the plan to read it: a CSV data set at the top of the thread group, and
111
+ `${username}`-style variables replacing the literals in the requests. That edit is
112
+ "Change values in place" below, and Atlas divides the rows between machines at run time,
113
+ so each user gets a different row.
114
+
115
+ **3. Do the dynamic values need handling?** Run `atlas-rec suggest`, show what it
116
+ found with its evidence, and pin anything it missed — see `atlas-correlate`.
117
+
118
+ **4. Are checks needed?** A 200 that returns a login page or an empty result is a
119
+ pass as far as the plan is concerned. Offer assertions on the responses that
120
+ matter, and debug them locally before uploading (see below).
121
+
122
+ **5. Upload and smoke-run it** — the rest of this skill, then `atlas-load-test`.
123
+
124
+ ## How these plans are put together
125
+
126
+ A recorded plan — and most plans in these projects — has the same skeleton, and
127
+ knowing it saves you from reading 700 lines of XML to find one value:
128
+
129
+ - **`Settings - Sleeps`** — a variables element at the top of the plan holding
130
+ `round_sleep`, `short_sleep` and `long_sleep`. Every pause in the plan is a
131
+ *Think Time* step reading one of them: `round_sleep` once per iteration,
132
+ `short_sleep` between steps the person clicked through quickly, `long_sleep`
133
+ where they paused. The pauses themselves stay enabled; **the variables element
134
+ is what switches them on and off.** Disabled, the variables do not exist, every
135
+ pause resolves to 0 ms, and the plan runs flat out. Enabled, its values are the
136
+ wait in milliseconds — typically 10s and 30s, so a four-step scenario takes
137
+ well over a minute per user.
138
+ - **`Settings - Host`** — variables for the target host, normally disabled so the
139
+ recorded URLs are used as-is. Enable and edit it to point the same plan at
140
+ another environment.
141
+ - **Cache and Cookie Managers, and HTTP Request Defaults**, applying to the whole
142
+ plan.
143
+ - **One thread group per scenario**, each holding numbered transactions
144
+ (`01 Open home page`) and numbered samplers inside them (`01.01 /`). The
145
+ numbering is what makes a results report readable — keep it when you add a
146
+ step.
147
+ - **Sizing through run-time settings** — `${__P(threads,..)}`, `${__P(rampup,..)}`
148
+ and `${__P(loops,..)}`, so `--args "-Jthreads=50"` scales the plan without
149
+ editing it. Note the sleep variables are **not** settings of that kind: `-J`
150
+ will not change them.
151
+
152
+ Merging a recorded scenario into an existing plan keeps **that plan's** settings,
153
+ not the recording's. A new recording has its sleeps switched off; a plan someone
154
+ has been running usually has them on, and the new scenario inherits that.
155
+
156
+ ## Debugging a plan locally
157
+
158
+ Running the plan yourself with one user is the fastest way to confirm a new
159
+ scenario, an assertion or a correlation actually works. It needs JMeter on the
160
+ machine (`jmeter -v`); when it is missing, say so and use a smoke run on Atlas
161
+ instead.
162
+
163
+ **Work on a copy.** Never debug the file you are about to upload:
164
+
165
+ ```bash
166
+ cp ./checkout.jmx ./debug.jmx
167
+ ```
168
+
169
+ **Check the sleeps, do not assume.** This is the single biggest time sink: with
170
+ the pauses on, a four-step scenario takes ~100 s per user instead of ~5 s, and
171
+ every re-check costs another two minutes.
172
+
173
+ ```bash
174
+ grep -n 'testname="Settings - Sleeps"' ./debug.jmx
175
+ ```
176
+
177
+ If the element does not carry `enabled="false"`, the pauses are live. Disable it
178
+ in the copy — the element only, not the pauses:
179
+
180
+ ```xml
181
+ <Arguments ... testname="Settings - Sleeps" enabled="false">
182
+ ```
183
+
184
+ **Cut the run down to what you are testing:** add `enabled="false"` to the thread
185
+ groups you are not debugging, and run one user, one iteration.
186
+
187
+ ```bash
188
+ JVM_ARGS="-XX:TieredStopAtLevel=1" HEAP="-Xms256m -Xmx512m" \
189
+ jmeter -n -t debug.jmx -l debug.jtl -Jthreads=1 -Jloops=1 \
190
+ -Jjmeter.save.saveservice.output_format=csv \
191
+ -Jjmeter.save.saveservice.assertion_results_failure_message=true >/dev/null 2>&1
192
+ awk -F, '{print $3" | "$4" | "$8" | "$9}' debug.jtl # label, code, ok, why not
193
+ ```
194
+
195
+ **Read the results file, not the console.** JMeter ends every non-GUI run with a
196
+ page of log4j shutdown lines that mean nothing; the `.jtl` is the answer. The
197
+ `JVM_ARGS`/`HEAP` prefix roughly halves JMeter's startup for a one-user run. A
198
+ four-step scenario like this takes about 5 seconds end to end — if it takes a
199
+ minute or more, the sleeps are still on.
200
+
201
+ **Restore anything you changed.** If you had to disable the sleeps in the real
202
+ plan rather than a copy — say, because the person asked you to debug that file —
203
+ note the original values and the enabled/disabled state first, put them back
204
+ before uploading, and confirm with the same `grep`. A plan uploaded with its
205
+ think time switched off hammers the target far harder than intended, and nothing
206
+ downstream will warn anyone.
207
+
208
+ **Prove an assertion can fail, cheaply.** An assertion that passes may simply
209
+ never have been evaluated. Check it against the recording before spending a run:
210
+ the capture file holds the real response bodies, so a JSON path or a text match
211
+ can be tested in a second with `python3`/`jq` — including the failing case. When
212
+ you do want JMeter to prove it, put the passing and failing variants in the same
213
+ copy, or start both runs at once, rather than one run after another.
214
+
215
+ ## Check before uploading
216
+
217
+ ```bash
218
+ atlas plan check ./checkout.jmx -p <project>
219
+ ```
220
+
221
+ This answers the questions that otherwise only surface as an empty dashboard an
222
+ hour later. With `-p` it also checks the plan's data files against what the
223
+ project actually holds. It exits non-zero when the plan would not produce
224
+ results, and reports:
225
+
226
+ - **A data file the plan reads that is not in the project.** This is the one that
227
+ hurts: every user in that thread group fails before sending a request, so the
228
+ group vanishes from the results *with no errors at all* while the other groups
229
+ look healthy.
230
+ - **A plan Atlas cannot attach its reporting to** — it would run and report
231
+ nothing.
232
+ - **A broken structure**, or no enabled thread group.
233
+ - **Fixed user counts**, meaning machines are the only way to scale it.
234
+ - Paths from another machine and GUI listeners are reported for information:
235
+ Atlas rewrites data-file paths to the uploaded file and switches off View
236
+ Results Tree and Simple Data Writer in the copy it deploys. Your stored file is
237
+ never modified.
238
+
239
+ ## Upload
240
+
241
+ ```bash
242
+ atlas files upload -p <project> ./checkout.jmx ./users.csv
243
+ ```
244
+
245
+ Same name replaces. Different name adds — so `--jmx` chooses which plan a run
246
+ uses, and a project can hold several. Uploading a plan does not start anything.
247
+
248
+ Then check it from the project's point of view, which is what will actually run:
249
+
250
+ ```bash
251
+ atlas plan check -p <project> --jmx checkout.jmx
252
+ ```
253
+
254
+ ## Data files
255
+
256
+ - **Names must match** what the plan reads. The plan referring to
257
+ `C:\data\users.csv` is fine as long as `users.csv` is uploaded — Atlas resolves
258
+ it. Nothing named `users.csv` in the project is not fine.
259
+ - **Rows are divided between machines**, not copied. 10,000 rows across 5
260
+ machines is 2,000 each, so no two users get the same row. Pass `--no-split` at
261
+ run time when every machine must see the whole file.
262
+ - **The first line is a header only if the plan says so.** Atlas reads that from
263
+ the plan's data-set configuration, so leave the file exactly as the plan
264
+ expects it — do not add or strip a header row to be helpful.
265
+ - Generating test data is fine and often useful; say what you generated and how
266
+ many rows, and make sure it matches the columns the plan expects.
267
+
268
+ ## Deleting
269
+
270
+ ```bash
271
+ atlas files rm -p <project> old-data.csv --yes
272
+ ```
273
+
274
+ Deletion is not undoable from here. Download first if there is any doubt, and
275
+ never delete a file you did not just upload without asking.
276
+
277
+ ## Finish the job
278
+
279
+ An uploaded plan is not a working plan. Smoke-run it — one machine, a couple of
280
+ users — and check the results contain data before anyone sizes it up. That flow
281
+ is in `atlas-load-test`, and reading the result is in `atlas-analyze`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudbeat/atlas-cli",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Atlas CLI — run JMeter load tests from CI and record scenarios",
5
5
  "main": "dist/cli.js",
6
6
  "bin": {
@@ -24,11 +24,13 @@
24
24
  },
25
25
  "license": "UNLICENSED",
26
26
  "scripts": {
27
- "build": "tsc",
27
+ "build": "tsc && node scripts/bundle-docs.js && node scripts/bundle-skills.js",
28
28
  "dev": "ts-node src/cli.ts",
29
29
  "start": "node dist/cli.js",
30
30
  "watch": "tsc --watch",
31
- "prepublishOnly": "npm run build"
31
+ "prepublishOnly": "npm run build",
32
+ "test:plan": "ts-node --compiler-options '{\"module\":\"commonjs\"}' test/plan.test.ts",
33
+ "test": "npm run test:plan"
32
34
  },
33
35
  "dependencies": {
34
36
  "chalk": "^4.1.2",