-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test(load-test): Performance tests for create dialog and search (#1331)
<!--- Provide a general summary of your changes in the Title above --> ## Description See commits for details ## Related Issue(s) - #1326 ## Verification - [ ] **Your** code builds clean without any errors or warnings - [x] Manual testing done (required) - [ ] Relevant automated test added (if you find this hard, leave it and we'll help out) ## Documentation - [ ] Documentation is updated (either in `docs`-directory, Altinnpedia or a separate linked PR in [altinn-studio-docs.](https://github.com/Altinn/altinn-studio-docs), if applicable) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Introduced new GitHub Actions workflows for K6 performance testing, allowing manual execution with customizable parameters. - Added performance testing scripts for end-user interactions and dialog creation using the K6 framework. - **Bug Fixes** - Improved handling of authorization headers in request parameter functions. - **Chores** - Updated `.gitignore` to exclude sensitive files and generated token files. - Added a script for generating tokens for service owners and end users. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Ole Jørgen Skogstad <[email protected]> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
- Loading branch information
1 parent
92967b6
commit b3a01e8
Showing
11 changed files
with
334 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
name: Run K6 performance test | ||
|
||
on: | ||
workflow_dispatch: | ||
inputs: | ||
apiVersion: | ||
description: 'API Version' | ||
required: true | ||
default: 'v1' | ||
environment: | ||
description: 'Environment' | ||
required: true | ||
default: 'staging' | ||
type: choice | ||
options: | ||
- test | ||
- staging | ||
- performance | ||
tokens: | ||
description: 'Tokens to generate; for create dialog, search, none, or both' | ||
required: true | ||
default: 'both' | ||
type: choice | ||
options: | ||
- both | ||
- enterprise | ||
- personal | ||
- none | ||
vus: | ||
description: 'Number of VUS' | ||
required: true | ||
type: number | ||
default: 10 | ||
duration: | ||
description: 'Duration of test, ie 30s, 1m, 10m' | ||
required: true | ||
default: 1m | ||
type: string | ||
testSuitePath: | ||
description: 'Path to test suite to run' | ||
required: true | ||
default: 'tests/k6/tests/serviceowner/performance/create-dialog.js' | ||
|
||
jobs: | ||
k6-performance: | ||
name: "Run K6 performance test" | ||
uses: ./.github/workflows/performance-workflows/workflow-run-k6-performance.yml | ||
secrets: | ||
TOKEN_GENERATOR_USERNAME: ${{ secrets.TOKEN_GENERATOR_USERNAME }} | ||
TOKEN_GENERATOR_PASSWORD: ${{ secrets.TOKEN_GENERATOR_PASSWORD }} | ||
K6_CLOUD_TOKEN: ${{ secrets.K6_CLOUD_TOKEN }} | ||
K6_CLOUD_PROJECT_ID: ${{ secrets.K6_CLOUD_PROJECT_ID }} | ||
with: | ||
environment: ${{ inputs.environment }} | ||
apiVersion: ${{ inputs.apiVersion }} | ||
testSuitePath: ${{ inputs.testSuitePath }} | ||
vus: ${{ inputs.vus }} | ||
duration: ${{ inputs.duration }} | ||
tokens: ${{ inputs.tokens }} | ||
|
55 changes: 55 additions & 0 deletions
55
.github/workflows/performance-workflows/workflow-run-k6-performance.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
name: Run K6 performance tests | ||
|
||
on: | ||
workflow_call: | ||
inputs: | ||
apiVersion: | ||
required: true | ||
type: string | ||
environment: | ||
required: true | ||
type: string | ||
testSuitePath: | ||
required: true | ||
type: string | ||
vus: | ||
required: true | ||
type: number | ||
duration: | ||
required: true | ||
type: string | ||
tokens: | ||
required: true | ||
type: string | ||
secrets: | ||
TOKEN_GENERATOR_USERNAME: | ||
required: true | ||
TOKEN_GENERATOR_PASSWORD: | ||
required: true | ||
K6_CLOUD_TOKEN: | ||
required: true | ||
K6_CLOUD_PROJECT_ID: | ||
required: true | ||
|
||
jobs: | ||
k6-test: | ||
runs-on: ubuntu-latest | ||
permissions: | ||
checks: write | ||
pull-requests: write | ||
steps: | ||
- name: Checkout code | ||
uses: actions/checkout@v4 | ||
- name: Setup k6 | ||
uses: grafana/setup-k6-action@v1 | ||
- name: Run K6 tests (${{ inputs.testSuitePath }}) | ||
run: | | ||
./tests/k6/tests/scripts/generate_tokens.sh ./tests/k6/tests/performancetest_data ${{ inputs.tokens }} | ||
k6 run ${{ inputs.testSuitePath }} --quiet --log-output=stdout --include-system-env-vars --vus=${{ inputs.vus }} --duration=${{ inputs.duration }} | ||
env: | ||
API_ENVIRONMENT: ${{ inputs.environment }} | ||
API_VERSION: ${{ inputs.apiVersion }} | ||
TOKEN_GENERATOR_USERNAME: ${{ secrets.TOKEN_GENERATOR_USERNAME }} | ||
TOKEN_GENERATOR_PASSWORD: ${{ secrets.TOKEN_GENERATOR_PASSWORD }} | ||
K6_CLOUD_TOKEN: ${{ secrets.K6_CLOUD_TOKEN }} | ||
K6_CLOUD_PROJECT_ID: ${{ secrets.K6_CLOUD_PROJECT_ID }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import { getEU, expect, expectStatusFor, describe } from "../../../common/testimports.js"; | ||
import { SharedArray } from 'k6/data'; | ||
import papaparse from 'https://jslib.k6.io/papaparse/5.1.1/index.js'; | ||
import { randomItem } from 'https://jslib.k6.io/k6-utils/1.2.0/index.js'; | ||
|
||
const filenameEndusers = '../../performancetest_data/.endusers-with-tokens.csv'; | ||
|
||
const endUsers = new SharedArray('endUsers', function () { | ||
try { | ||
const csvData = papaparse.parse(open(filenameEndusers), { header: true, skipEmptyLines: true }).data; | ||
if (!csvData.length) { | ||
throw new Error('No data found in CSV file'); | ||
} | ||
csvData.forEach((user, index) => { | ||
if (!user.token || !user.ssn) { | ||
throw new Error(`Missing required fields at row ${index + 1}`); | ||
} | ||
}); | ||
return csvData; | ||
} catch (error) { | ||
throw new Error(`Failed to load end users: ${error.message}`); | ||
} | ||
}); | ||
|
||
export let options = { | ||
summaryTrendStats: ['avg', 'min', 'med', 'max', 'p(95)', 'p(99)', 'p(99.5)', 'p(99.9)', 'count'], | ||
thresholds: { | ||
'http_req_duration{name:simple search}': [], | ||
'http_reqs{name:simple search}': [], | ||
}, | ||
}; | ||
|
||
export default function() { | ||
if ((options.vus === undefined || options.vus === 1) && (options.iterations === undefined || options.iterations === 1)) { | ||
simpleSearch(endUsers[0]); | ||
} | ||
else { | ||
simpleSearch(randomItem(endUsers)); | ||
} | ||
} | ||
|
||
export function simpleSearch(enduser) { | ||
let paramsWithToken = { | ||
headers: { | ||
Authorization: "Bearer " + enduser.token | ||
}, | ||
tags: { name: 'simple search' } | ||
} | ||
let defaultParty = "urn:altinn:person:identifier-no:" + enduser.ssn; | ||
let defaultFilter = "?Party=" + defaultParty; | ||
describe('Perform simple dialog list', () => { | ||
let r = getEU('dialogs' + defaultFilter, paramsWithToken); | ||
expectStatusFor(r).to.equal(200); | ||
expect(r, 'response').to.have.validJsonBody(); | ||
}); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
ssn,resource,scopes | ||
08895699684,super-simple-service,digdir:dialogporten |
2 changes: 2 additions & 0 deletions
2
tests/k6/tests/performancetest_data/serviceowners-staging.csv
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
org,orgno,scopes,resource | ||
digdir,991825827,digdir:dialogporten.serviceprovider,super-simple-service |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
#!/bin/bash | ||
|
||
# Check if required environment variables are set | ||
if [ -z "$TOKEN_GENERATOR_USERNAME" ] || [ -z "$TOKEN_GENERATOR_PASSWORD" ] || [ -z "$API_ENVIRONMENT" ]; then | ||
echo "Error: TOKEN_GENERATOR_USERNAME, TOKEN_GENERATOR_PASSWORD, and API_ENVIRONMENT must be set" | ||
exit 1 | ||
fi | ||
|
||
# Function to display usage information | ||
usage() { | ||
echo "Usage: $0 <testdatafilepath> <tokens>" | ||
echo " <testdatafilepath>: Path to the test data files" | ||
echo " <tokens>: Type of tokens to generate (both, enterprise, or personal)" | ||
exit 1 | ||
} | ||
|
||
# Validate arguments | ||
if [ $# -ne 2 ]; then | ||
usage | ||
fi | ||
|
||
tokengenuser=${TOKEN_GENERATOR_USERNAME} | ||
tokengenpasswd=${TOKEN_GENERATOR_PASSWORD} | ||
|
||
env="" | ||
case $API_ENVIRONMENT in | ||
"test") | ||
env="at21" ;; | ||
"staging") | ||
env="tt02" ;; | ||
"performance") | ||
env="yt01" ;; | ||
*) | ||
echo "Error: Unknown api environment $API_ENVIRONMENT" | ||
exit 1 ;; | ||
esac | ||
|
||
testdatafilepath=$1 | ||
tokens=$2 | ||
|
||
# Validate tokens argument | ||
if [[ ! "$tokens" =~ ^(both|enterprise|personal)$ ]]; then | ||
echo "Error: Invalid token type. Must be 'both', 'enterprise', or 'personal'." | ||
usage | ||
fi | ||
|
||
serviceowner_datafile="$testdatafilepath/serviceowners-$API_ENVIRONMENT.csv" | ||
serviceowner_tokenfile="$testdatafilepath/.serviceowners-with-tokens.csv" | ||
enduser_datafile="$testdatafilepath/endusers-$API_ENVIRONMENT.csv" | ||
enduser_tokenfile="$testdatafilepath/.endusers-with-tokens.csv" | ||
|
||
if [ "$tokens" = "both" ] || [ "$tokens" = "enterprise" ]; then | ||
if [ ! -f "$serviceowner_datafile" ]; then | ||
echo "Error: Input file not found: $serviceowner_datafile" | ||
exit 1 | ||
fi | ||
echo "org,orgno,scopes,resource,token" > $serviceowner_tokenfile | ||
while IFS=, read -r org orgno scopes resource | ||
do | ||
url="https://altinn-testtools-token-generator.azurewebsites.net/api/GetEnterpriseToken?org=$org&env=$env&scopes=$scopes&orgno=$orgno&ttl=3600" | ||
token=$(curl -s -f $url -u "$tokengenuser:$tokengenpasswd" ) | ||
if [ $? -ne 0 ]; then | ||
echo "Error: Failed to generate enterprise token for: $env, $org, $orgno, $scopes " | ||
continue | ||
fi | ||
echo "$org,$orgno,$scopes,$resource,$token" >> $serviceowner_tokenfile | ||
status=$? | ||
if [ $status -ne 0 ]; then | ||
echo "Error: Failed to write enterprise token to file for: $env, $org, $orgno, $scopes" | ||
fi | ||
done < <(tail -n +2 $serviceowner_datafile) | ||
fi | ||
|
||
if [ "$tokens" = "both" ] || [ "$tokens" = "personal" ]; then | ||
if [ ! -f "$enduser_datafile" ]; then | ||
echo "Error: Input file not found: $enduser_datafile" | ||
exit 1 | ||
fi | ||
echo "ssn,resource,scopes,token" > $enduser_tokenfile | ||
while IFS=, read -r ssn resource scopes | ||
do | ||
url="https://altinn-testtools-token-generator.azurewebsites.net/api/GetPersonalToken?env=$env&scopes=$scopes&pid=$ssn&ttl=3600" | ||
token=$(curl -s -f $url -u "$tokengenuser:$tokengenpasswd" ) | ||
if [ $? -ne 0 ]; then | ||
echo "Error: Failed to generate personal token for: $ssn, $scopes " | ||
continue | ||
fi | ||
echo "$ssn,$resource,$scopes,$token" >> $enduser_tokenfile | ||
status=$? | ||
if [ $status -ne 0 ]; then | ||
echo "Error: Failed to write personal token to file for: $ssn, $scopes" | ||
fi | ||
done < <(tail -n +2 $enduser_datafile) | ||
fi |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import { postSO, expect, describe } from "../../../common/testimports.js"; | ||
import { SharedArray } from 'k6/data'; | ||
import papaparse from 'https://jslib.k6.io/papaparse/5.1.1/index.js'; | ||
import { default as dialogToInsert } from '../testdata/01-create-dialog.js'; | ||
import { randomItem } from 'https://jslib.k6.io/k6-utils/1.2.0/index.js'; | ||
|
||
const filenameServiceowners = '../../performancetest_data/.serviceowners-with-tokens.csv'; | ||
const filenameEndusers = `../../performancetest_data/endusers-${__ENV.API_ENVIRONMENT}.csv`; | ||
|
||
const serviceOwners = new SharedArray('serviceOwners', function () { | ||
return papaparse.parse(open(filenameServiceowners), { header: true, skipEmptyLines: true }).data; | ||
}); | ||
|
||
const endUsers = new SharedArray('endUsers', function () { | ||
return papaparse.parse(open(filenameEndusers), { header: true, skipEmptyLines: true }).data; | ||
}); | ||
|
||
export let options = { | ||
summaryTrendStats: ['avg', 'min', 'med', 'max', 'p(95)', 'p(99)', 'p(99.5)', 'p(99.9)', 'count'], | ||
thresholds: { | ||
'http_req_duration{scenario:default}': [`max>=0`], | ||
'http_req_duration{name:create dialog}': [], | ||
'http_reqs{name:create dialog}': [], | ||
}, | ||
}; | ||
|
||
export default function() { | ||
if ((options.vus === undefined || options.vus === 1) && (options.iterations === undefined || options.iterations === 1)) { | ||
createDialog(serviceOwners[0], endUsers[0]); | ||
} | ||
else { | ||
createDialog(randomItem(serviceOwners), randomItem(endUsers)); | ||
} | ||
} | ||
|
||
export function createDialog(serviceOwner, endUser) { | ||
var paramsWithToken = { | ||
headers: { | ||
Authorization: "Bearer " + serviceOwner.token | ||
}, | ||
tags: { name: 'create dialog' } | ||
} | ||
|
||
describe('create dialog', () => { | ||
let r = postSO('dialogs', dialogToInsert(endUser.ssn), paramsWithToken); | ||
expect(r.status, 'response status').to.equal(201); | ||
}); | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters