Open
Conversation
…2>&1 | tee test/k6/k6-output.txt
…r routes tested and stricter API runtime check
There was a problem hiding this comment.
Pull request overview
Integrates a basic k6-based load test into the NodeBB repo to simulate concurrent traffic against common unauthenticated pages/API endpoints and capture performance/availability signals.
Changes:
- Add a k6 test script that hits several NodeBB routes with simple status/latency checks.
- Add a captured example output log from a local k6 run.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
test/k6/load-test.mjs |
Defines k6 scenario options and a per-iteration flow hitting multiple endpoints with check() assertions. |
test/k6/k6-output.txt |
Adds a recorded console output artifact from a single k6 run. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
Comment on lines
+10
to
+12
| // Test homepage | ||
| let res = http.get('http://localhost:4567/'); | ||
| check(res, { |
Comment on lines
+12
to
+15
| check(res, { | ||
| 'homepage status is 200': (r) => r.status === 200, | ||
| 'homepage loads in < 500ms': (r) => r.timings.duration < 500, | ||
| }); |
Comment on lines
+11
to
+38
| let res = http.get('http://localhost:4567/'); | ||
| check(res, { | ||
| 'homepage status is 200': (r) => r.status === 200, | ||
| 'homepage loads in < 500ms': (r) => r.timings.duration < 500, | ||
| }); | ||
|
|
||
| // Test recent topics | ||
| let recent = http.get('http://localhost:4567/recent'); | ||
| check(recent, { | ||
| 'recent topics status is 200': (r) => r.status === 200, | ||
| 'recent topics loads in < 500ms': (r) => r.timings.duration < 500, | ||
| }); | ||
|
|
||
| // Test popular topics | ||
| let popular = http.get('http://localhost:4567/popular'); | ||
| check(popular, { | ||
| 'popular topics status is 200': (r) => r.status === 200, | ||
| }); | ||
|
|
||
| // Test categories page | ||
| let categories = http.get('http://localhost:4567/categories'); | ||
| check(categories, { | ||
| 'categories status is 200': (r) => r.status === 200, | ||
| 'categories loads in < 500ms': (r) => r.timings.duration < 500, | ||
| }); | ||
|
|
||
| // Test API endpoint | ||
| let api = http.get('http://localhost:4567/api/recent'); |
Comment on lines
+196
to
+199
| ✓ homepage status is 200 | ||
| ✗ homepage loads in < 500ms | ||
| ↳ 98% — ✓ 1800 / ✗ 20 | ||
| ✓ recent topics status is 200 |
Comment on lines
+1
to
+42
|
|
||
| /\ Grafana /‾‾/ | ||
| /\ / \ |\ __ / / | ||
| / \/ \ | |/ / / ‾‾\ | ||
| / \ | ( | (‾) | | ||
| / __________ \ |_|\_\ \_____/ | ||
|
|
||
| execution: local | ||
| script: test/k6/load-test.mjs | ||
| output: - | ||
|
|
||
| scenarios: (100.00%) 1 scenario, 50 max VUs, 1m30s max duration (incl. graceful stop): | ||
| * default: 50 looping VUs for 1m0s (gracefulStop: 30s) | ||
|
|
||
|
|
||
| running (0m01.0s), 50/50 VUs, 0 complete and 0 interrupted iterations | ||
| default [ 2% ] 50 VUs 0m01.0s/1m0s | ||
|
|
||
| running (0m02.0s), 50/50 VUs, 0 complete and 0 interrupted iterations | ||
| default [ 3% ] 50 VUs 0m02.0s/1m0s | ||
|
|
||
| running (0m03.0s), 50/50 VUs, 50 complete and 0 interrupted iterations | ||
| default [ 5% ] 50 VUs 0m03.0s/1m0s | ||
|
|
||
| running (0m04.0s), 50/50 VUs, 50 complete and 0 interrupted iterations | ||
| default [ 7% ] 50 VUs 0m04.0s/1m0s | ||
|
|
||
| running (0m05.0s), 50/50 VUs, 100 complete and 0 interrupted iterations | ||
| default [ 8% ] 50 VUs 0m05.0s/1m0s | ||
|
|
||
| running (0m06.0s), 50/50 VUs, 100 complete and 0 interrupted iterations | ||
| default [ 10% ] 50 VUs 0m06.0s/1m0s | ||
|
|
||
| running (0m07.0s), 50/50 VUs, 150 complete and 0 interrupted iterations | ||
| default [ 12% ] 50 VUs 0m07.0s/1m0s | ||
|
|
||
| running (0m08.0s), 50/50 VUs, 150 complete and 0 interrupted iterations | ||
| default [ 13% ] 50 VUs 0m08.0s/1m0s | ||
|
|
||
| running (0m09.0s), 50/50 VUs, 200 complete and 0 interrupted iterations | ||
| default [ 15% ] 50 VUs 0m09.0s/1m0s | ||
|
|
Comment on lines
+4
to
+6
| export const options = { | ||
| vus: 50, // 50 virtual users | ||
| duration: '60s', // run for 60 seconds |
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Overview
This PR integrates k6 testing into the YC 26 instance of the NodeBB repo, which is a dynamic testing tool used to test loads. k6 allows us to simulate concurrent users using the NodeBB webapp, and measures performance metrics including response times, webapp open failure rates, and throughput. The k6 test file load-test.js is written in javascript, which is a good tool and integrates well with NodeBB's node.js codebase.
Tool Name & Description
The tool used in this PR is k6. k6 is an open source dynamic analysis load testing tool which is typically used to evaluate the performance and scalability of web applications, like NodeBB, by simulating concurrent/simultaneous users and measuring how the system behaves under heavy traffic. I personally chose to test our codebase using k6, since NodeBB is a web-app that would naturally have a large concurrent user base, and the ability to concurrently run without issues is a core function of a discussion forum webapp, thus stress testing traffic management is something crucial, especially after making changes and adding features such as anonymous posting, supported by instructor, resolving posts, and a admin view of announcement viewing lists, features that rely on instantaneous change and live data syncs.
Installation Evidence:
@types/k6 was added to package.json as a dependency, k6 binary was installed locally via direct download from v.0.55.0 of k6 on github, and test scripts were created in test/k6/load-test.js
Types of Problems the Tool Catches
k6 helps us identify performance issues introduced by the new features we added into NodeBB including
What I tested specifically
Results:
All k6 checks on the endpoints ran successfully, some failed such as homepage loading within 500ms, but 0 failed requests, successful passing runs on average response time within established thresholds, handled 50 users at once without errors, shows viability for usage for a class-setting use of NodeBB.
Customization & Configurations:
1) Priori:
Routes/pages to test must be manually added to the test file, k6 can't automatically find endpoints
2) Over time:
Pros:
Cons:
How can/should we integrate this into the development process?
k6 fits well into our development process as a performance validation tool for each of our added features implemented in the NodeBB codebase. Specifically, we can run local testing, by running k6 against the local NodeBB instance with our plugins and extensions to make sure our new features don't compromise traffic handling and scalability. We can also integrate k6 testing into our git workflow, by ensuring k6 tests pass and uphold stability thresholds that we want NodeBB to run at, before we commit, push or merge changes to our repository for our new features, given the features we implemented are mostly related to simultaneous use cases. Finally, we can implement k6 into CI/CD to check for performance when new features are added every time a small change or feature is pushed.
False Positives/False Negatives
Because k6 is a dynamic tool that measures real runtime behavior rather than a static analysis tool, it would generally have less false positives and false negatives. Regardless, some false positives that could occur would be incomplete endpoint coverage, meaning k6 not fully testing the runtime behavior after a certain function is triggered, but rather in its idle state, as well as lacking tests for authenticated routes that require login/role specific rendering. Some false negatives that could occur would be indication of performance problems that might be less meaningful/relevant to our webapp, such as failures from first time requests, or local runtime problems due to lack of cpu or gpu on the local device.