-
Notifications
You must be signed in to change notification settings - Fork 0
Add load tests #453
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
Open
alexeyr-ci
wants to merge
12
commits into
master
Choose a base branch
from
alexeyr/benchmark
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Add load tests #453
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
5fb9faa
Initial k6 load test
alexeyr 441a8d7
Add streaming load test using k6
alexeyr 573cd19
Fix ESLint for K6
alexeyr 47f60cd
Switch the streaming load test from browser to request API
alexeyr fc4ed67
Move _util to lib/
alexeyr 48c639a
Format k6/**
alexeyr d48e6fe
Update check for rendered components
alexeyr 6b11238
Improve defaultOptions
alexeyr 84a5e20
Add benchmarking to docs
alexeyr b59fd67
Switch streaming back to browser tests
alexeyr a25cc54
Add spec/dummy/bin/prod
alexeyr 72f5115
Add thresholds for failing test
alexeyr File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -293,12 +293,40 @@ If you run `rspec` at the top level, you'll see this message: `require': cannot | |
|
|
||
| After running a test, you can view the coverage results in SimpleCov reports by opening `coverage/index.html`. | ||
|
|
||
| ### Benchmarking | ||
| You'll need to [install `k6`](https://grafana.com/docs/k6/latest/set-up/install-k6/) first and start the dummy app in production mode (using [bin/prod](https://github.com/shakacode/react_on_rails_pro/blob/master/spec/dummy/bin/prod)). | ||
| You can remove even more overhead by using | ||
| ```sh | ||
| bin/prod &> /dev/null | ||
| ``` | ||
|
|
||
| The benchmarking scripts are in `k6` directory, so you can run, for example: | ||
| ```sh | ||
| k6 run k6/root.js | ||
| ``` | ||
| to exercise the main page of the dummy app. | ||
|
|
||
| For browser tests like `k6/streaming.js`, it's recommended to include `K6_BROWSER_LOG=fatal` for actual measurement after verifying the tests work. | ||
| It avoids unnecessary overhead from outputting console messages. | ||
|
|
||
| For significant changes, please make sure to run all benchmarks before and after, and include the results in the PR. | ||
| Later they will be added to CI, if we can make sure the results there are stable enough. | ||
|
|
||
| If you add significant new functionality and add a page in the dummy app showing it, consider adding the corresponding benchmark as well. | ||
|
|
||
| #### Debugging the benchmark scripts | ||
| You can add `-e DEBUG_K6=true` to run only a single iteration while showing HTTP requests and responses. See | ||
| [How to debug k6 load testing scripts](https://github.com/grafana/k6-learn/blob/main/Modules/III-k6-Intermediate/01-How-to-debug-k6-load-testing-scripts.md) for more suggestions if needed. | ||
|
|
||
| ### Debugging | ||
| Start the sample app like this for some debug printing: | ||
|
|
||
| ```sh | ||
| TRACE_REACT_ON_RAILS=true && foreman start -f Procfile.dev | ||
| TRACE_REACT_ON_RAILS=true overmind start -f Procfile.dev | ||
| ``` | ||
| Using `overmind` instead of `foreman` lets you restart separate processes, connect with them when stopped with a `debugger` call, and so on. | ||
| See https://railsnotes.xyz/blog/overmind-better-bin-dev-for-your-procfile-dev for more details. | ||
| If you don't need that, you can use `bin/dev` or `foreman` as well. | ||
|
|
||
| # Releasing | ||
| Contact Justin Gordon, [email protected] | ||
|
|
||
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| export const url = (path) => `${__ENV.BASE_URL ?? 'http://localhost:3000'}/${path}`; | ||
|
|
||
| /** @type {(envVar: string) => boolean} */ | ||
| const envToBoolean = (envVar) => { | ||
| const value = __ENV[envVar]; | ||
| return !!value && ['true', '1', 'yes'].includes(value.toLowerCase()); | ||
| }; | ||
|
|
||
| /** | ||
| * @param {boolean} [inScenario=isBrowser] Is this used as `scenarios: { <scenarioName>: defaultOptions(...) }`? | ||
| * @param {boolean} [isBrowser=false] Is this a browser test? | ||
| * @param {boolean} [isDebug=env.DEBUG_K6] Are we running in debug mode? | ||
| * @param {import('k6/options').Options} [otherOptions] Other options to merge in | ||
| * @return {import('k6/options').Options} | ||
| * */ | ||
| export const defaultOptions = ({ | ||
| isBrowser = false, | ||
| isDebug = envToBoolean('DEBUG_K6'), | ||
| // Browser tests options can only be set inside `scenarios` | ||
| // https://grafana.com/docs/k6/latest/using-k6-browser/ | ||
| inScenario = isBrowser, | ||
| ...otherOptions | ||
| } = {}) => { | ||
| const thresholds = { | ||
| checks: ['rate>0.90'], | ||
| http_req_failed: ['rate<0.05'], | ||
| }; | ||
| const baseOptions = isDebug | ||
| ? { | ||
| vus: 1, | ||
| iterations: 1, | ||
| httpDebug: inScenario ? undefined : 'full', | ||
| thresholds, | ||
| ...otherOptions, | ||
| } | ||
| : { | ||
| vus: 10, | ||
| duration: '30s', | ||
| thresholds, | ||
| ...otherOptions, | ||
| }; | ||
| if (inScenario) { | ||
| // See https://github.com/grafana/k6-learn/blob/main/Modules/III-k6-Intermediate/08-Setting-load-profiles-with-executors.md | ||
| baseOptions.executor = isDebug ? 'shared-iterations' : 'constant-vus'; | ||
| } | ||
| return isBrowser | ||
| ? { | ||
| ...baseOptions, | ||
| options: { | ||
| browser: { | ||
| type: 'chromium', | ||
| }, | ||
| }, | ||
| } | ||
| : baseOptions; | ||
| }; |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| import { check } from 'k6'; | ||
| import http from 'k6/http'; | ||
| import { defaultOptions, url } from './lib/util.js'; | ||
|
|
||
| export const options = defaultOptions(); | ||
|
|
||
| export default () => { | ||
| const rootUrl = url(''); | ||
| check(http.get(rootUrl), { | ||
| 'status was 200': (res) => res.status === 200, | ||
| 'renders components successfully': (res) => { | ||
| const body = res.html().text(); | ||
| return Object.entries({ | ||
| // This is visible on the page in the browser 4 times, but for some reason, the one under | ||
| // "Server Rendered React Component Without Redux" is missing in `body`. | ||
| 'Hello, Mr. Server Side Rendering!': 3, | ||
| 'Hello, Mrs. Client Side Rendering!': 2, | ||
| 'Hello, Mrs. Client Side Hello Again!': 1, | ||
| 'Hello ES5, Mrs. Client Side Rendering!': 1, | ||
| 'Hello WORLD! Will this work?? YES! Time to visit Maui': 1, | ||
| }).every(([text, count]) => body.split(text).length >= count + 1); | ||
| }, | ||
| }); | ||
| }; |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| import { check } from 'k6'; | ||
| import { browser } from 'k6/browser'; | ||
| import { defaultOptions, url } from './lib/util.js'; | ||
|
|
||
| const streamingUrl = url('stream_async_components?delay=5'); | ||
|
|
||
| export const options = { | ||
| scenarios: { | ||
| browser: defaultOptions({ isBrowser: true }), | ||
| }, | ||
| }; | ||
|
|
||
| export default async () => { | ||
| const page = await browser.newPage(); | ||
| try { | ||
| const response = await page.goto(streamingUrl); | ||
| check(response, { | ||
| 'status was 200': (res) => res.status() === 200, | ||
| }); | ||
| await page.waitForFunction(() => !document.body.textContent.includes('Loading'), { | ||
| // in milliseconds | ||
| timeout: 5000, | ||
| }); | ||
| check(await page.locator('html').textContent(), { | ||
| 'has all comments': (text) => { | ||
| // can't define commentIds as a constant outside, this runs in browser context | ||
| const commentIds = [1, 2, 3, 4]; | ||
| return commentIds.every((id) => text.includes(`Comment ${id}`)); | ||
| }, | ||
| }); | ||
| } finally { | ||
| await page.close(); | ||
| } | ||
| }; |
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,9 @@ | ||
| <%= stream_react_component("StreamAsyncComponents", props: @app_props_server_render, prerender: true, trace: true, id: "StreamAsyncComponents-react-component-0") %> | ||
| <%= | ||
| props = @app_props_server_render | ||
| delay = params[:delay] | ||
| props = props.merge(baseDelayMs: delay.to_i) unless delay.nil? | ||
| stream_react_component("StreamAsyncComponents", props: props, prerender: true, trace: true, id: "StreamAsyncComponents-react-component-0") | ||
| %> | ||
| <hr/> | ||
|
|
||
| <h1>React Rails Server Streaming Server Rendered Async React Components</h1> |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| #!/usr/bin/env bash | ||
|
|
||
| RAILS_ENV=production NODE_ENV=production overmind start -f Procfile.static |
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
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
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not used.