@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.
- package/README.md +46 -19
- package/dist/api.js +20 -0
- package/dist/cli.js +34 -6
- package/dist/commands/analyze.js +118 -0
- package/dist/commands/capacity.js +99 -0
- package/dist/commands/docs.js +57 -0
- package/dist/commands/files.js +18 -4
- package/dist/commands/plan.js +100 -0
- package/dist/commands/record.js +11 -1
- package/dist/commands/results.js +13 -7
- package/dist/commands/schema.js +86 -0
- package/dist/commands/skills.js +111 -0
- package/dist/commands/tests.js +73 -0
- package/dist/docs/agent-setup.md +109 -0
- package/dist/docs/agent-tasks.md +169 -0
- package/dist/docs/ai-agents.md +90 -0
- package/dist/docs/auth.md +74 -0
- package/dist/docs/automation.md +150 -0
- package/dist/docs/ci.md +105 -0
- package/dist/docs/clusters.md +48 -0
- package/dist/docs/commands.md +155 -0
- package/dist/docs/files.md +86 -0
- package/dist/docs/generators.md +52 -0
- package/dist/docs/getting-started.md +85 -0
- package/dist/docs/index.json +110 -0
- package/dist/docs/projects.md +50 -0
- package/dist/docs/recorder.md +143 -0
- package/dist/docs/results.md +79 -0
- package/dist/docs/running.md +80 -0
- package/dist/docs/skills.md +88 -0
- package/dist/docs/test-plans.md +92 -0
- package/dist/docs/troubleshooting.md +79 -0
- package/dist/plan.js +250 -0
- package/dist/skills/AGENTS.md +70 -0
- package/dist/skills/atlas-analyze/SKILL.md +104 -0
- package/dist/skills/atlas-correlate/SKILL.md +89 -0
- package/dist/skills/atlas-load-test/SKILL.md +154 -0
- package/dist/skills/atlas-record/SKILL.md +167 -0
- package/dist/skills/atlas-run/SKILL.md +109 -0
- package/dist/skills/atlas-test-plan/SKILL.md +281 -0
- 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
|
+
"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",
|