Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Nedbank k6 load test #6436

Merged
merged 15 commits into from
Feb 7, 2025
Merged
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
Loading