-
Notifications
You must be signed in to change notification settings - Fork 3.2k
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
chore(driver): fix integration test retry configuration #18643
Conversation
Thanks for taking the time to open a PR!
|
Test summaryRun details
View run in Cypress Dashboard ➡️ This comment has been generated by cypress-bot as a result of this project's GitHub integration settings. You can manage this integration in this project's settings in the Cypress Dashboard |
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.
I can't observe this actually retrying like it's supposed to. I see flaky driver tests still in CI. Locally, I tried to validate these changes by adding this spec to packages/driver
and using yarn cypress:run
:
let i = 0; let j = 0; let k = 0
const N = 2
it('fails twice then succeeds', () => {
if (i++ < N) throw new Error(`failed ${i}`)
})
it('fails twice then succeeds', () => {
if (j++ < N) throw new Error(`failed ${j}`)
})
it('fails twice then succeeds', () => {
if (k++ < N) throw new Error(`failed ${k}`)
})
It does retry the first test one time with these changes, but it does not retry twice like it's supposed to:
Also, none of the subsequent test failures are retried.
Changing N
to 1
makes the first test pass (since it retries once) but the next 2 still fail and are not retried:
let isActuallyInteractive | ||
|
||
isActuallyInteractive = Cypress.config('isInteractive') | ||
if (!isActuallyInteractive) { | ||
// we want to only enable retries in runMode | ||
// and because we set `isInteractive` above | ||
// we have to set retries here | ||
Cypress.config('retries', 2) | ||
} |
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.
This was here as a workaround to the fact that we set isInteractive = true
on line 19.
Cypress's getTestRetries
switches on isInteractive
to decide how many retries to use:
cypress/packages/driver/src/cypress.ts
Lines 147 to 159 in 2eb8ef1
this.getTestRetries = function () { | |
const testRetries = this.config('retries') | |
if (_.isNumber(testRetries)) { | |
return testRetries | |
} | |
if (_.isObject(testRetries)) { | |
return testRetries[this.config('isInteractive') ? 'openMode' : 'runMode'] | |
} | |
return null | |
} |
Locally, it was returning 0 for me in this PR, which makes sense since this workaround was removed.
packages/driver/cypress.json
Outdated
}, | ||
"retries": { | ||
"runMode": 2, | ||
"openMode": 0 |
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.
I don't think this will work because of isInteractive
being forced to true
@@ -163,6 +170,8 @@ describe('src/cy/commands/navigation', () => { | |||
}) | |||
|
|||
it('throws passing 2 invalid arguments', { defaultCommandTimeout: 200, retries: 1 }, (done) => { | |||
expect(Cypress.config('retries')).to.eq(1) |
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.
testing the value of Cypress.getTestRetries()
may be good to add somewhere
Looking at the failures / flakey tests listed in the last Cypress comment, retries have been enabled. |
@@ -1,8 +1,7 @@ | |||
const { $ } = Cypress | |||
|
|||
let isActuallyInteractive | |||
const isActuallyInteractive = Cypress.config('isInteractive') |
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.
This is the change to enable retries
@@ -66,6 +66,12 @@ export const shouldBeCalledWithCount = (num) => (stub) => wrapped(stub).should(' | |||
|
|||
export const shouldNotBeCalled = (stub) => wrapped(stub).should('not.be.called') | |||
|
|||
export const assertLogLength = (logs, expectedLength) => { |
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.
Helper to log the list of logs received to help debug when log length is different than expected.
packages/driver/cypress/integration/commands/navigation_spec.js
Outdated
Show resolved
Hide resolved
packages/driver/cypress/integration/commands/navigation_spec.js
Outdated
Show resolved
Hide resolved
packages/driver/cypress/integration/commands/navigation_spec.js
Outdated
Show resolved
Hide resolved
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.
My supplied test case from earlier works, but some stuff is still not retrying: https://app.circleci.com/pipelines/github/cypress-io/cypress/26345/workflows/825f5705-1c96-4ff5-b0d4-f43234e78612/jobs/994369/parallel-runs/1
There's no evidence of retrying on that failure in the logs.
You can observe this locally running yarn cypress:run --headed --no-exit
, some tests will fail and not be retried, and some will be retried. Not sure what's happening, there's no per-test config in this file...
@flotwig You linked to the CircleCI logs. If you look in the Cypress Dashboard results you will see retries are working. I had a similar concern about the logs not showing a retry & when testing locally with the following example, I was able to observe retries when running
I am currently running |
Co-authored-by: Matt Henkes <mjhenkes@gmail.com>
Some tests are retrying, some tests aren't retrying. That test code does work now, but some real specs in
Observe the results of Peek.2021-11-09.13-33.mp4Earlier tests in the file do retry, so I'm not sure what causes this yet. But, it's not retrying. |
@flotwig Thanks for the example. I'll take a look. |
// user does an asynchronous `done`, so double-check | ||
// that the test has not already passed before timing out | ||
return | ||
} |
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.
For anyone curious to reproduce this issue, you can comment this out and runt his test to consistently see the error shown in the video Zach linked:
it('should not be true', { defaultCommandTimeout: 1 }, (done) => {
cy.on('fail', (err) => {
expect(err.message).to.eq('expected false to be true')
done()
})
cy.noop(false).should('be.true')
})
* develop: (329 commits) chore: Update Chrome (stable) to 96.0.4664.45 (#18931) fix: Loading of specs with % in the filename (#18877) chore: refactor `create` into class `$Cy` (#18715) chore: Update Chrome (beta) to 96.0.4664.45 (#18891) fix: flaky `system-tests-firefox` job (#18848) release 9.0.0 feat: ensure major release have conduit app wait on localhost:3000 fix install-required-node use --legacy-peer-deps feat: ensure major release fix darwin node install chore(driver): fix integration test retry configuration (#18643) feat(deps): update dependency electron to v15 🌟 (#18317) chore: Bind this correctly when setting response headers with cy.route() (#18859) feat: create config package for config validation (#18589) chore: patch `winston` to suppress `padLevels` warning (#18824) chore: test out major release build fix: remove outdated npm registry links (#18727) fix: Adding an existing command with `Cypress.Commands.add()` will throw an error (#18587) ...
Test flakiness in
packages/driver
has been observed and tests have not been retried as expected. This change enables the retry configuration in the integration tests via the cypress configuration.