Skip to content

Commit

Permalink
Add Nedbank k6 load test (#6436)
Browse files Browse the repository at this point in the history
* Nedbank implementation

* Moved nedbank entity and change error message

* Add data attributes and nedbank cronjob endpoint

* Change order of cron job

* Add comments and finish first stage

* Add validation and refactor payment functions

* lower duplicate numbers for test

* Update PA multipliers

* Add fixes

* remove unused files

* Update k6/helpers/registration-default.data.js

Co-authored-by: RubenGeo <34537157+RubenGeo@users.noreply.github.com>

* Update k6/models/programs.js

Co-authored-by: RubenGeo <34537157+RubenGeo@users.noreply.github.com>

* Update k6/tests/payment100kRegistrationNedbank.js

Co-authored-by: RubenGeo <34537157+RubenGeo@users.noreply.github.com>

* Update k6/tests/retryFailedJobsOnStartupDuringQueueProcessing.js

Co-authored-by: RubenGeo <34537157+RubenGeo@users.noreply.github.com>

* Fix missing error response log

---------

Co-authored-by: Ruben <vandervalk@geoit.nl>
Co-authored-by: RubenGeo <34537157+RubenGeo@users.noreply.github.com>
  • Loading branch information
3 people authored and diderikvw committed Feb 7, 2025
1 parent 9ba8127 commit 35e08fe
Show file tree
Hide file tree
Showing 12 changed files with 113 additions and 26 deletions.
1 change: 1 addition & 0 deletions k6/helpers/custom-data-attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,6 @@ export const FinancialServiceProviders = {
intersolveVisa: 'Intersolve-visa',
safaricom: 'Safaricom',
commercialBankEthiopia: 'Commercial-bank-ethiopia',
nedbank: 'Nedbank',
excel: 'Excel',
};
11 changes: 11 additions & 0 deletions k6/helpers/registration-default.data.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,14 @@ export const registrationSafaricom = {
nationalId: '32121321',
nameAlternate: 'test',
};

export const registrationNedbank = {
referenceId: '01dc9451-1273-484c-b2e8-ae21b51a96ab',
programFinancialServiceProviderConfigurationName:
FinancialServiceProviders.nedbank,
phoneNumber: '2708374149',
preferredLanguage: 'en',
paymentAmountMultiplier: 1,
maxPayments: 6,
fullName: 'Franklin Floyd',
};
12 changes: 6 additions & 6 deletions k6/models/initalize-payment.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,15 @@ const registrationsPage = new RegistrationsModel();
const programsPage = new ProgramsModel();

export default class InitializePaymentModel {
constructor() {}

initializePayment(
resetScript,
programId,
registration,
duplicateNumber,
paymentId,
maxTimeoutAttempts,
status,
minPassRatePercentage,
paymentNr,
amount,
) {
// reset db
Expand All @@ -33,13 +32,14 @@ export default class InitializePaymentModel {
resetPage.duplicateRegistrations(duplicateNumber);
// Change status of all PAs to included and check response
programsPage.updateRegistrationStatusAndLog(programId, 'included');

paymentsPage.createPayment(programId, amount);
// Create payment
paymentsPage.createPayment(programId, amount, paymentNr);
// Monitor that 10% of payments is successful and then stop the test
return paymentsPage.getPaymentResults(
programId,
status,
maxTimeoutAttempts,
paymentId,
paymentNr,
duplicateNumber,
minPassRatePercentage,
);
Expand Down
18 changes: 9 additions & 9 deletions k6/models/payments.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@ import config from './config.js';
const { baseUrl } = config;

export default class paymentsModel {
constructor() {}
createPayment(programId, amount) {
createPayment(programId, amount, paymentNr) {
const url = `${baseUrl}api/programs/${programId}/payments`;
const payload = JSON.stringify({
payment: 3,
payment: paymentNr,
amount,
});
const params = {
Expand All @@ -23,26 +22,27 @@ export default class paymentsModel {

getPaymentResults(
programId,
status,
maxTimeoutAttempts,
paymentNr,
totalAmountPowerOfTwo,
passRate,
) {
const maxAttempts = maxTimeoutAttempts;
let attempts = 0;
let successPercentage = 0;
let selectedStatusPercentage = 0;

while (attempts < maxAttempts) {
const url = `${baseUrl}api/programs/${programId}/payments/${paymentNr}`;
const res = http.get(url);
const responseBody = JSON.parse(res.body);
const totalPayments = Math.pow(2, totalAmountPowerOfTwo);
successPercentage =
(parseInt(responseBody.success.count) / totalPayments) * 100;
selectedStatusPercentage =
(parseInt(responseBody[status].count) / totalPayments) * 100;

if (successPercentage >= passRate) {
if (selectedStatusPercentage >= passRate) {
console.log(
`Success: The percentage of successful payments (${successPercentage}%) is at or above the pass rate (${passRate}%).`,
`Success: The percentage of successful payments (${selectedStatusPercentage}%) is at or above the pass rate (${passRate}%).`,
);
return res;
}
Expand All @@ -53,7 +53,7 @@ export default class paymentsModel {
return {
status: 500,
body: JSON.stringify({
error: `Failed after ${maxAttempts} attempts without reaching the pass rate of ${passRate}%. Last recorded pass rate was ${successPercentage}%.`,
error: `Failed after ${maxAttempts} attempts without reaching the pass rate of ${passRate}%. Last recorded pass rate was ${selectedStatusPercentage}%.`,
}),
};
}
Expand Down
6 changes: 6 additions & 0 deletions k6/models/programs.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,4 +125,10 @@ export default class ProgramsModel {
}
return statusCount;
}

nedbankCronJob() {
const url = `${baseUrl}api/financial-service-providers/nedbank`;
const res = http.patch(url);
return res;
}
}
62 changes: 62 additions & 0 deletions k6/tests/payment100kRegistrationNedbank.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { check, fail, sleep } from 'k6';
import { Counter } from 'k6/metrics';

import { registrationNedbank } from '../helpers/registration-default.data.js';
import InitializePaymentModel from '../models/initalize-payment.js';

const initializePayment = new InitializePaymentModel();

const duplicateNumber = 17; // '17' leads to 131k registrations
const resetScript = 'nedbank-program';
const programId = 1;
const paymentNr = 1;
const maxTimeoutAttempts = 800;
const status = 'waiting';
const minPassRatePercentage = 10;
const amount = 20;

export const options = {
thresholds: {
http_req_failed: ['rate<0.01'], // http errors should be less than 1%
failed_checks: ['count<1'], // fail the test if any check fails
},
vus: 1,
duration: '80m',
iterations: 1,
};

const failedChecks = new Counter('failed_checks');

function checkAndFail(response, checks) {
const result = check(response, checks);
if (!result) {
failedChecks.add(1);
fail('One or more checks failed');
}
}

export default function () {
const monitorPayment = initializePayment.initializePayment(
resetScript,
programId,
registrationNedbank,
duplicateNumber,
maxTimeoutAttempts,
status,
minPassRatePercentage,
paymentNr,
amount,
);
checkAndFail(monitorPayment, {
'Payment progressed successfully status 202': (r) => {
if (r.status != 202) {
const responseBody = JSON.parse(r.body);
console.log(responseBody.error || r.status);
}
console.log('status: ', r.status);
return r.status == 200;
},
});

sleep(1);
}
6 changes: 4 additions & 2 deletions k6/tests/payment100kRegistrationOCW.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ const initializePayment = new InitializePaymentModel();
const duplicateNumber = 17; // '17' leads to 131k registrations
const resetScript = 'nlrc-multiple';
const programId = 3;
const paymentId = 3;
const paymentNr = 3;
const maxTimeoutAttempts = 800;
const status = 'success';
const minPassRatePercentage = 10;
const amount = 11.11;

Expand Down Expand Up @@ -40,9 +41,10 @@ export default function () {
programId,
registrationVisa,
duplicateNumber,
paymentId,
maxTimeoutAttempts,
status,
minPassRatePercentage,
paymentNr,
amount,
);
checkAndFail(monitorPayment, {
Expand Down
8 changes: 5 additions & 3 deletions k6/tests/payment100kRegistrationSafaricom.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ import InitializePaymentModel from '../models/initalize-payment.js';

const initializePayment = new InitializePaymentModel();

const duplicateNumber = 7; // '17' leads to 131k registrations
const duplicateNumber = 17; // '17' leads to 131k registrations
const resetScript = 'safari-program';
const programId = 1;
const paymentId = 3;
const paymentNr = 3;
const maxTimeoutAttempts = 800;
const status = 'success';
const minPassRatePercentage = 10;
const amount = 10;

Expand Down Expand Up @@ -40,9 +41,10 @@ export default function () {
programId,
registrationSafaricom,
duplicateNumber,
paymentId,
maxTimeoutAttempts,
status,
minPassRatePercentage,
paymentNr,
amount,
);
checkAndFail(monitorPayment, {
Expand Down
3 changes: 2 additions & 1 deletion k6/tests/performanceDuringPayment.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const metricsPage = new metricstsModel();
const duplicateNumber = 5;
const programId = 3;
const paymentId = 3;
const paymentNr = 3;
const maxTimeoutAttempts = 600;
const minPassRatePercentage = 50;
const amount = 11.11;
Expand Down Expand Up @@ -60,7 +61,7 @@ export default function () {
});

// Do the payment
const doPayment = paymentsPage.createPayment(programId, amount);
const doPayment = paymentsPage.createPayment(programId, amount, paymentNr);
checkAndFail(doPayment, {
'Payment successfully done status 202': (r) => {
if (r.status != 202) {
Expand Down
5 changes: 3 additions & 2 deletions k6/tests/retryFailedJobsOnStartupDuringQueueProcessing.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,15 @@ const loginPage = new loginModel();
const duplicateNumber = 7; // This leads to 128 registrations
const programId = 3;
const paymentId = 3;
const paymentNr = 3;
const maxTimeoutAttempts = 400;
const minPassRatePercentage = 100;
const amount = 10;

export const options = {
thresholds: {
// In this case the health check runs multiple times and so of the responses are going to be 500 before service is up
http_req_failed: ['rate<0.30'], // http errors should be less than 30%
http_req_failed: ['rate<0.40'], // http errors should be less than 40%
failed_checks: ['count<1'], // fail the test if any check fails
},
vus: 1,
Expand Down Expand Up @@ -63,7 +64,7 @@ export default function () {
});

// Do the payment
const doPayment = paymentsPage.createPayment(programId, amount);
const doPayment = paymentsPage.createPayment(programId, amount, paymentNr);
checkAndFail(doPayment, {
'Payment successfully done status 202': (r) => {
if (r.status != 202) {
Expand Down
5 changes: 3 additions & 2 deletions k6/tests/statusChangePaymentInLargeProgram.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ const paymentsPage = new PaymentsModel();
const registrationsPage = new RegistrationsModel();

const resetScript = 'nlrc-multiple';
const duplicateNumber = 15;
const duplicateNumber = 15; // should be 15
const programId = 3;
const paymentId = 3;
const paymentNr = 3;
const maxTimeoutAttempts = 200;
const minPassRatePercentage = 10;
const amount = 10;
Expand Down Expand Up @@ -124,7 +125,7 @@ export default function () {
});

// Do the payment
const doPayment = paymentsPage.createPayment(programId, amount);
const doPayment = paymentsPage.createPayment(programId, amount, paymentNr);
checkAndFail(doPayment, {
'Payment successfully done status 202': (r) => {
if (r.status != 202) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
update "121-service".registration_attribute_data
set "value" = CAST(10000000000 + floor(random() * 90000000000) AS bigint)
set "value" = CAST(left("value", 2) || CAST(100000000 + floor(random() * 900000000) AS bigint) AS bigint)
WHERE "programRegistrationAttributeId" IN (SELECT id FROM "121-service".program_registration_attribute WHERE "name" = 'phoneNumber' OR "name" = 'whatsappPhoneNumber');
;
update "121-service".registration r
Expand Down

0 comments on commit 35e08fe

Please sign in to comment.