Skip to content

Commit

Permalink
Testing K6 Dynamic Analysis Tool (#54)
Browse files Browse the repository at this point in the history
* added k6 dynamic stress test

* install k6 in workflow

* run k6 test in workflow

* fixed k6 file name typo

* fixed k6 modules

* test github workflow

* test for failure

* fix syntax

* Update threshold

* conduct browser tests

* add ui checks and adjust thresholds

* move k6 performance test after deployment

* remove redundant tests

* update threshold

* adjust threshold

---------

Co-authored-by: Michaelli8899 <[email protected]>
Co-authored-by: dominicteh1 <[email protected]>
  • Loading branch information
3 people authored Oct 30, 2024
1 parent 59a04fb commit be18222
Show file tree
Hide file tree
Showing 9 changed files with 124 additions and 2 deletions.
3 changes: 2 additions & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ logs/
.eslintrc
test/files
*.min.js
install/docker/
install/docker/
k6-test.js
11 changes: 11 additions & 0 deletions .github/workflows/azure-deploy-f24.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ on:
push:
branches:
- f24
pull_request:
branches:
- f24
workflow_dispatch:

concurrency:
Expand Down Expand Up @@ -58,3 +61,11 @@ jobs:
slot-name: 'Production'
publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE_DD104B6B0E3A46A5BE6C5F708D090CF7 }}
package: .

- name: Setup K6
uses: grafana/setup-k6-action@v1

- name: Run local k6 test
uses: grafana/run-k6-action@v1
with:
path: k6-test.js
2 changes: 1 addition & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ jobs:
}
run: |
node app --setup="${SETUP}" --ci="${CI}"
- name: Run ESLint
run: npm run lint

Expand Down
Binary file modified dump.rdb
Binary file not shown.
110 changes: 110 additions & 0 deletions k6-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import http from 'k6/http';
import { browser } from 'k6/browser';
import { check, sleep } from 'k6';

export const options = {
thresholds: {
http_req_failed: [
{
threshold: 'rate<0.20', // http errors should be less than 10%
abortOnFail: true,
delayAbortEval: '10s',
},
],
http_req_duration: [
{
threshold: 'p(95) < 3000',// 95% of requests should be below 2s
abortOnFail: true,
delayAbortEval: '10s',
},
],
},
scenarios: {
performance: {
executor: 'ramping-vus',
stages : [
{ duration: '10s', target: 10 },
{ duration: '30s', target: 20 },
{ duration: '30s', target: 40 },
{ duration: '30s', target: 80 },
{ duration: '30s', target: 160 },
]
},
ui: {
executor: 'shared-iterations',
options: {
browser: {
type: 'chromium',
},
},
exec: 'ui_test',
}
}
};

// The function that defines VU logic.
//
// See https://grafana.com/docs/k6/latest/examples/get-started-with-k6/ to learn more
// about authoring k6 scripts.
//
export default function() {
const res = http.get('https://nodebb-team-bulbasaur1.azurewebsites.net/');
sleep(1);
};

export async function ui_test(){
const page = await browser.newPage();
try {

//login as admin
await page.goto('https://nodebb-team-bulbasaur1.azurewebsites.net/login');
await page.locator('input[name="username"]').fill('admin');
await page.locator('input[name="password"]').fill('bulbasaur');
const submitButton = page.locator('button[type="submit"]');
await Promise.all([
page.waitForNavigation({ waitUntil: 'domcontentloaded', timeout: 60000 }),
submitButton.click()
]);

// go to testing topic
await page.goto("https://nodebb-team-bulbasaur1.azurewebsites.net/topic/5/do-not-post-here", { waitUntil: 'networkidle' });

// test for solve/unsolve in topic
await page.waitForSelector('div[component="topic/solve"]');
const solveButton = page.locator('div[component="topic/solve"]');
const solveButtonStatus = await solveButton.textContent();
console.log('solveButtonStatus:', solveButtonStatus);
const newSolveButton = page.locator('div[component="topic/solve"]');
if (solveButtonStatus && solveButtonStatus.includes('Unsolved')) {
console.log('Clicking the solve button because status is Unsolved...');
await solveButton.click();
await page.waitForTimeout(2000); // Wait for the button state to change after clicking

// Verify the button has changed to 'Solved'
const newSolveButtonText = await solveButton.textContent();
const solvedStatusCheck = newSolveButtonText.includes('Solved');
console.log(`New solve button status: ${newSolveButtonText}`);
check(solvedStatusCheck, {
'is status Solved': (status) => status === true,
});
} else {
console.log('Clicking the solve button because status is Unsolved...');
await solveButton.click();
await page.waitForTimeout(2000); // Wait for the button state to change after clicking

// Verify the button has changed to 'Unsolved'
const newSolveButtonText = await solveButton.textContent();
const solvedStatusCheck = newSolveButtonText.includes('Unsolved');
console.log(`New solve button status: ${newSolveButtonText}`);
check(solvedStatusCheck, {
'is status Unsolved': (status) => status === true,
});
}
//reset solve button status
await solveButton.click();


} finally{
await page.close();
}
}
Binary file added screenshots/topic-page.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added screenshots/topic.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added screenshots/topic2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added screenshots/topic3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit be18222

Please sign in to comment.