6234 - Stress test - Data entry: Tables & NDP - #6254
Conversation
| editNdp(headers, countryIso, ndps) | ||
| } | ||
|
|
||
| sleep(randomInt(pauseMinSeconds, pauseMaxSeconds)) |
There was a problem hiding this comment.
The if else logic is a bit difficult to understand.
Maybe it's better if we have one stress test per case ?
Data entry
Edit NDP
Edit descriptions
@sorja what do you think ?
There was a problem hiding this comment.
Sounds good
I would do something similar to:
src/tools/stressTest/tableData.ts
src/tools/stressTest/ndpData.ts
src/tools/stressTest/descriptions.ts
--
Something else:
Not sure where we should fetch validations (GET request), for me it would make more sense to:
in case of {table data / ndp / description}:
write: {}
read: {}
Means:
when stress testing table data, I would also try to fetch the same data
when stress testing ndp (e.g. year 2020), i would try to fetch the same ndp to see that it responds
etc
Does this make sense?
-- After thought --
Maybe we can fetch both validations AND table data in the canary?
There was a problem hiding this comment.
Done. I split it into one test per case: tableData/ and ndp/
run.sh now takes the test as an argument:
./src/tools/stressTest/run.sh <host> <email> <password> # tableData (default)
./src/tools/stressTest/run.sh <host> <email> <password> ndp@sorja I added a canary at a fixed rate (2/s) that fetches the data being written and its validations 👍
| export const read = (data: { token: string }): void => { | ||
| const headers = { Cookie: `fra-auth-token=${data.token}` } | ||
| const countryIso = countries[randomInt(0, countries.length - 1)] | ||
| getTableData(headers, countryIso) |
There was a problem hiding this comment.
should we also get validations here?
There was a problem hiding this comment.
i see now that they are fetched with getTableData
should we use getValidations?
| const headers = { 'Content-Type': 'application/json', Cookie: `fra-auth-token=${data.token}` } | ||
| const countryIso = countries[__VU % countries.length] // spreads simulated users across countries | ||
| editTableCells(headers, countryIso) | ||
| sleep(randomInt(pauseMinSeconds, pauseMaxSeconds)) |
There was a problem hiding this comment.
not sure if this is needed, i think constant pause or no pause is enough
for stress test, does it add value to have a random interval pause?
There was a problem hiding this comment.
Yes, the initial idea was to simulate 100 users, so a pause like this helps mimic user behaviour better.
| headers, | ||
| tags: { name: 'validations/table-data GET' }, | ||
| }) | ||
| check(validations, { 'table validations ok': (res) => res.status === 200 }) |
There was a problem hiding this comment.
what do you think?
| check(validations, { 'table validations ok': (res) => res.status === 200 }) | |
| // import { RequestUtils } ... | |
| check(validations, { 'table validations ok': RequestUtils.isOk) |
| const params = `${cycleParams(countryIso)}§ionName=extentOfForest` | ||
|
|
||
| const one = http.get( | ||
| `${baseUrl}/api/cycle-data/national-data-points/national-data-point?${params}&year=${ndp.year}`, |
There was a problem hiding this comment.
we should use ApiEndpoints . please, let's not hardcode api endpoints
There was a problem hiding this comment.
We can't use ApiEndPoint here (mentioned in readme) these files run inside k6, not Node. k6 bundles the scripts with its own loader, which doesn't understand our tsconfig path aliases, and ApiEndPoint imports its own modules through those aliases (meta/api/endpoint/...), so the import fails. Only type imports work, because they are erased at build time.
I can check if I can add a pre-bundle step in the sh script and maybe then we can import normal platform code.
There was a problem hiding this comment.
I checked the docs and we can do something like this in run.sh to bundle before running the tests using rolldown (a vite dependency):
#!/bin/sh
# Runs a stress test against the given environment. See README.md.
<...usage...>
# Paths are resolved relative to this file, so run.sh works from any directory
dir="$(dirname "$0")"
root="$dir/../../.."
test="${4:-tableData}"
bundle="$root/.tmp/stressTest-$test.js" # a file per test so concurrent runs of different tests don't collide
# Bundle the test first so it is possible resolve import aliases
mkdir -p "$root/.tmp"
"$root/node_modules/.bin/rolldown" "$dir/$test/index.ts" --external k6 --external k6/http \
--format esm --platform neutral --tsconfig "$root/tsconfig.json" --file "$bundle" >/dev/null
exec k6 run -e HOST="$1" -e STRESS_TEST_EMAIL="$2" -e STRESS_TEST_PASSWORD="$3" "$bundle"
@sorja @minotogna what do you think? this way we can import ApiEndPoint, Numbers.randomInt, RequestUtils.isOk etc...
| const originalDataPoint = { ...ndp, values: { ...ndp.values, forestArea: String(randomInt(0, 1000)) } } | ||
| const params = `${cycleParams(countryIso)}§ionName=extentOfForest` | ||
| const response = http.put( | ||
| `${baseUrl}/api/cycle-data/national-data-points/national-data-point/original-data?${params}`, |
There was a problem hiding this comment.
we should use ApiEndpoints . please, let's not hardcode api endpoints
| ) | ||
| check(one, { 'ndp read ok': (res) => res.status === 200 }) | ||
|
|
||
| const validations = http.get(`${baseUrl}/api/cycle-data/validations/national-data-points?${params}`, { |
There was a problem hiding this comment.
we should use ApiEndpoints . please, let's not hardcode api endpoints
|
|
||
| const ndpsByCountry: Record<string, Array<OriginalDataPoint>> = {} | ||
| countries.forEach((countryIso) => { | ||
| const response = http.get(`${baseUrl}/api/cycle-data/national-data-points?${cycleParams(countryIso)}`, { headers }) |
There was a problem hiding this comment.
we should use ApiEndpoints . please, let's not hardcode api endpoints
| tableName: cell.tableName, | ||
| values: [{ colName: cell.colName, value: { raw: String(randomInt(0, 1000)) }, variableName: cell.variableName }], | ||
| } | ||
| const response = http.patch(`${baseUrl}/api/cycle-data/table/nodes?${params}`, JSON.stringify(body), { |
There was a problem hiding this comment.
we should use ApiEndpoints . please, let's not hardcode api endpoints
|
|
||
| // mergeOdp=false like UI requests | ||
| const tableData = http.get( | ||
| `${baseUrl}/api/cycle-data/table/table-data?${params}&countryISOs[]=${countryIso}&mergeOdp=false`, |
There was a problem hiding this comment.
we should use ApiEndpoints . please, let's not hardcode api endpoints
| ) | ||
| check(tableData, { 'table data ok': (res) => res.status === 200 }) | ||
|
|
||
| const validations = http.get(`${baseUrl}/api/cycle-data/validations/table-data?${params}`, { |
There was a problem hiding this comment.
we should use ApiEndpoints . please, let's not hardcode api endpoints
| @@ -0,0 +1 @@ | |||
| export const randomInt = (min: number, max: number): number => min + Math.floor(Math.random() * (max - min + 1)) | |||
There was a problem hiding this comment.
maybe better our utils Numbers.randomInt ?
|
Should we have util for urls? Something like |
No description provided.