-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Tests slow down over time when performing several XHR requests calls in single test #6783
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
Comments
cy.type()
cy.type()
calls in single test
cy.type()
calls in single test
It seems we may experience the same issue. We started to integrate cypress-tests a few month ago in our GWT project. Longer running tests, tend to get slower the longer they are, eventually running into timeouts (headless runs, I have a test which runs for about 2m 40sec (162 clicks, 266 gets, 50 shoulds, 10 types, 2 reloads, 1 visit and a few waits, producing about 300 XHR request), if I simply split it into 7 consecutive tests, without any other changes, it runs about 30% faster. |
I suspect this is due to the immense amount of forced reflows that is happening. Cypress triggers this every time it calls getBoundingClientRect (and its friends), as well as when determining visibility, and probably more, This has been explained before and also seems to be why a failing test causes consecutive tests to slow down, as a failing test doesn't close the command log (confirmed by patching Cypress to default to closed-logs, where the issue is absent). |
Cypress will also trigger reflow upon auto-scrolling the command log, as well as updating the time passed (we patched away all of these things in our CI environment). |
Thanks for these pointers! I investigated the auto-scrolling behavior a bit. First I tried replacing the auto-scrolling with a CSS-only solution using Flexbox and Then I hacked a simple test with a windowed list using react-virtualized for the command log, and that performed a lot better, around 110 seconds for the same test case. I only changed the listing of Here's how I made the alternative auto-scroll (omitting diff --git a/packages/reporter/package.json b/packages/reporter/package.json
index 8c3cc293f..d5d3dd6e5 100644
--- a/packages/reporter/package.json
+++ b/packages/reporter/package.json
@@ -23,6 +23,7 @@
"@reach/dialog": "0.6.1",
"@reach/visually-hidden": "0.6.1",
"@types/chai-enzyme": "0.6.7",
+ "@types/react-virtualized": "9.21.10",
"chai": "3.5.0",
"chai-enzyme": "1.0.0-beta.1",
"classnames": "2.2.6",
@@ -40,6 +41,7 @@
"prop-types": "15.7.2",
"react": "16.12.0",
"react-dom": "16.12.0",
+ "react-virtualized": "9.21.2",
"sinon": "7.5.0",
"webpack": "4.35.3",
"webpack-cli": "3.3.2"
diff --git a/packages/reporter/src/commands/command.tsx b/packages/reporter/src/commands/command.tsx
index 831598249..a803f2143 100644
--- a/packages/reporter/src/commands/command.tsx
+++ b/packages/reporter/src/commands/command.tsx
@@ -118,6 +118,7 @@ interface Props {
appState: AppState
events: Events
runnablesStore: RunnablesStore
+ style?: React.CSSProperties
}
@observer
@@ -132,11 +133,12 @@ class Command extends Component<Props> {
}
render () {
- const { model, aliasesWithDuplicates } = this.props
+ const { model, aliasesWithDuplicates, style } = this.props
const message = model.displayMessage
return (
- <li
+ <div
+ style={style}
className={cs(
'command',
`command-name-${model.name ? nameClassName(model.name) : ''}`,
@@ -199,7 +201,7 @@ class Command extends Component<Props> {
</div>
</FlashOnClick>
{this._duplicates()}
- </li>
+ </div>
)
}
diff --git a/packages/reporter/src/hooks/hooks.tsx b/packages/reporter/src/hooks/hooks.tsx
index 60dfab11b..9b442d27f 100644
--- a/packages/reporter/src/hooks/hooks.tsx
+++ b/packages/reporter/src/hooks/hooks.tsx
@@ -2,6 +2,8 @@ import cs from 'classnames'
import _ from 'lodash'
import { observer } from 'mobx-react'
import React from 'react'
+import { List, ListRowProps } from 'react-virtualized'
+import AutoSizer from 'react-virtualized-auto-sizer'
import Command from '../commands/command'
import Collapsible from '../collapsible/collapsible'
import HookModel from './hook-model'
@@ -17,23 +19,44 @@ const HookHeader = ({ name }: HookHeaderProps) => (
)
export interface HookProps {
+ useAlternativeAutoScroll: boolean
model: HookModel
}
-const Hook = observer(({ model }: HookProps) => (
+const Hook = observer(({ useAlternativeAutoScroll, model }: HookProps) => (
<li className={cs('hook-item', { 'hook-failed': model.failed })}>
<Collapsible
header={<HookHeader name={model.name} />}
headerClass='hook-name'
isOpen={true}
>
- <ul className='commands-container'>
- {_.map(model.commands, (command) => <Command key={command.id} model={command} aliasesWithDuplicates={model.aliasesWithDuplicates} />)}
- </ul>
+ {useAlternativeAutoScroll ? renderWindowedAutoScroll(model) : renderOriginalAutoScroll(model) }
</Collapsible>
</li>
))
+const renderOriginalAutoScroll = (model: HookModel) => (
+ <ul className='commands-container'>
+ {_.map(model.commands, (command) => <Command key={command.id} model={command} aliasesWithDuplicates={model.aliasesWithDuplicates} />)}
+ </ul>
+)
+
+const renderWindowedAutoScroll = (model: HookModel) => (
+ <List
+ className='commands-container'
+ height={600}
+ rowCount={model.commands.length}
+ rowHeight={21}
+ rowRenderer={renderRow(model)}
+ scrollToIndex={model.commands.length - 1}
+ width={600}
+ />
+)
+
+const renderRow = (model: HookModel) =>
+ ({ index, style }: ListRowProps) =>
+ <Command key={model.commands[index].id} model={model.commands[index]} aliasesWithDuplicates={model.aliasesWithDuplicates} style={style} />
+
export interface HooksModel {
hooks: Array<HookModel>
}
@@ -44,7 +67,7 @@ export interface HooksProps {
const Hooks = observer(({ model }: HooksProps) => (
<ul className='hooks-container'>
- {_.map(model.hooks, (hook) => <Hook key={hook.id} model={hook} />)}
+ {_.map(model.hooks, (hook) => <Hook key={hook.id} model={hook} useAlternativeAutoScroll={true} />)}
</ul>
)) Auto-scrolling needs to be disabled in the Cypress UI to properly test the alternative one. |
Just confirmed that this is still reproducible in 6.1.0 |
Another example of this bug: #14219 |
The code for this is done in cypress-io/cypress#17243, but has yet to be released. |
Released in This comment thread has been locked. If you are still experiencing this issue after upgrading to |
Current behavior:
Typing into several inputs in a single test where there are XHR requests that goes out during each keypress event - like
keyup
or similar - causes the tests to slow down over time.The network request responses do not seem to be responding any slower over time.
This slowness does not occur if you split up the typing across several tests.
Desired behavior:
Performance of running tests should stay the same over time
Test code to reproduce
❗️ Looping through input in a single test
Causes slowdown - maybe because we are saving a lot of XHR request data for every command
spec.js
index.html
Starting to slow down
Now really slow towards the end
❗️ Looping through clicking button in a single test
The slowness is not isolated to the
.type()
commandspec.js
index.html
✅ Looping through input over different tests
No slowdown - even with
numTestsMemory
kept at50
.✅ Looping through input without XHR requests
No slowdown
spec.js
index.html
Versions
4.2.0 - tried to track this down to some regression in earlier version, but couldn't find any correlation.
The text was updated successfully, but these errors were encountered: