-
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
Option to abort on first failure #518
Comments
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
The use-case I have for this is that I need my authentication tests to pass first - if they don't all subsequent tests will fail. Although the other tests will fail in the before hooks, it still slows things down unnecessarily (30 seconds per test file). I have to name my test 1auth so that it runs first and whitelist a cookie which contains a token required for the other tests to pass. Cypress.Cookies.defaults({
whitelist: 'token',
}) I was hoping to do something like this in my auth tests to stop running tests on fail; before(() => {
Cypress.on('fail', () => {
Cypress.runner.stop()
})
}) It does stop the test runner, but it doesn't fail any tests so I get 3/3 tests passed and a green build which is not the intended outcome. I also tried adding am intentional failing test before stopping cypress, but then the test runner continues. |
I have a temporary solution that I think can help someone. I just add an after each in my utilities file imported by all my specs. afterEach(function() {
if (this.currentTest.state === 'failed') {
Cypress.runner.stop()
}
}); I take advantage of Mocha offering a way to check the state of the last test. |
@danh91 I've been following this thread for months, and finally someone found a way! Awesome! |
This no longer works for me with Cypress 3.x. |
@harvitronix We changed how specs are run in 3.0 so that the files are run isolated. This means the |
Yes we've waited to implement this feature due to how aborting is much more complex now. We likely need to allow for multiple abort strategies abortStrategy: 'spec' | 'run' One would abort just the spec, one would abort the entire run. This becomes even more complex with parallelization. |
@jennifer-shehane that's exactly right. Totally understand it gets much more complex now. Would love to have the options you describe, @brian-mann. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Hi, loving Cypress, but not being able to stop our CI build for a failing test is stopping me from being able to use this in CI, and will especially be a problem in CD. I've searched quite thoroughly and hope I'm missing something somewhere, but it seems like this is related to this thread? If so, is there any progress / planned work on this solution? Cheers. |
@drumheadrob your issue is very different - you are saying that the |
We are currently working on the underlying processes needed to 'cancel' a run and any other queued spec files, which is a precursor to the work needed to 'abort' the rest of the tests on first failure. |
Some news right here? I am facing the very same problem, we were not able to use cypress on our CI. |
This comment has been minimized.
This comment has been minimized.
Are you still working on this feature ? |
We have the same situation, paying for cypress dashboard on private repos but our tests (now ~400 or so) are taking more and more time to complete. Much needed to stop early so our pipeline is freed up for the next PR to execute. |
It will be cool feature |
Another hack for making the spec fail (as I'd expect): if (
this?.currentTest?.state === "failed" // plus more conditions for retries
) {
...
if ("state" in cy && typeof cy.state === "function") {
cy.state("test").state = "failed";
}
...
} |
Just a note: the above workaround implies you are not using arrow functions for your test definitions. |
Correct, it should be clear to anyone following along with this that for const failEarly: Mocha.Func = function failEarly() { // could also be anonymous
// `this` is Mocha.Context
...
} |
I'm now finding this really doesn't do anything, AFAICT, and it looks suspiciously wrong anyway. I'm going to stop jumping through hoops assuming there are things I can do that aren't in the public API. |
@jennifer-shehane, can you comment on whether any of these strategies ought to work with v12+? I've been upgrading from v9, and at this point, don't have a strategy that aborts early on a failed test, marks the spec as failed, marks remaining tests as either Pending or Skipped, and then moves on (some may want the entire suite to stop, but we weren't doing that in the past). Thank you |
Based on this example by @drumslave-git, I came up with something that I think is working globally: export const failEarly = (runModeOnly = true) => {
if (runModeOnly && Cypress.config("isInteractive")) return; // headless runs only
const failedTest: Record<string, string | undefined> = {};
beforeEach(function() {
const specName = Cypress.spec.name;
if (failedTest[specName]) {
cy.log(
`*** Spec has failed. You will see an error emitted from beforeEach, but only need to fix failing tests ***`
);
}
cy.wrap(failedTest[specName]).should("be.undefined");
});
afterEach(function() {
const retryCount = Cypress.currentRetry;
const specName = Cypress.spec.name;
if (
this?.currentTest?.state === "failed" &&
Number.isInteger(retryCount) &&
getRunTypeRetries() <= retryCount
) {
failedTest[
specName
] = `Previous test, "${this.currentTest.title}", failed. This spec will be aborted.`;
}
});
};
const getRunTypeRetries = () => {
const retryConfig = Cypress.config("retries");
let configuredRetries = 0;
if (typeof retryConfig === "number" && Number.isInteger(retryConfig)) {
configuredRetries = retryConfig;
}
if (typeof retryConfig === "object" && null !== retryConfig) {
if (
retryConfig.runMode &&
Number.isInteger(retryConfig.runMode) &&
!Cypress.config("isInteractive")
) {
configuredRetries = retryConfig.runMode;
}
if (
retryConfig.openMode &&
Number.isInteger(retryConfig.openMode) &&
Cypress.config("isInteractive")
) {
configuredRetries = retryConfig.openMode;
}
}
return configuredRetries;
}; I imported const runModeOnly = !Cypress.env("BROWSER_FAIL_EARLY") == true;
failEarly(runModeOnly); with the idea that I can add Note, I'm using cypress-terminal-report to display those |
Options with If the current test is failed, it cancels all subsequent tests within the same container. Since I only use one level of nesting (ie This uses the Mocha
Works either on the global Cypress before(() => {
// Skip subsequent tests in spec when one fails.
(cy.state('runnable').ctx as Mocha.Context).currentTest.parent.bail(true);
}); Update: Note that this is a fix for an older Cypress version version, recent comments suggest it no longer works, see #518 (comment) Update 2: I was told that cypress/packages/driver/src/cypress/cy.ts Lines 1075 to 1079 in 22aacb1
Note that it is marked |
Is that the solution for 12.6.0 and later: https://docs.cypress.io/guides/guides/command-line#auto-cancel-after-runs ? |
Thanks for pointing this out. Will give it a try when we have a chance to upgrade |
I've spent half the day trying to find a way to prevent Cypress from continuing after failure, simply to preserve the debug data that what I'm testing left me for debugging. After what feels like a dozen different approaches that didn't work at all or not for my case, I went and bruteforced it this way.
What I did NOT expect was this to work. "Best case" expectation was that it does click the "Stop" button, but keeps "rolling" from momentum (it's dozen Promise-chains). If you're not using TypeScript, you can even reduce it to just |
before(() => {
// Skip subsequent tests in spec when one fails.
(cy.state('runnable').ctx as Mocha.Context).currentTest.parent.bail(true);
}); It seems
It seems that
But the good news is that BloodyRain2k's solution did work. You can either gate it with an environment variable (as in the original code), or make a function out of it: export default function enableFastFail() {
Cypress.on('test:after:run', (attrs, test) => {
if (test.isFailed()) {
const stop = window.top?.document.querySelector(
'.reporter button.stop'
) as HTMLElement;
stop.click();
}
});
}; That way, when you want the runner to stop after the first fail, you just temporarily import |
This works for me with Cypress 13.3.2
|
As far as I can see the most of solutions are about Cypress Runner: |
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
Yes, it worked for me. |
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
I had a problem with this solution as it prevented tests from being retried. If anyone else also suffers from this, you can filter error messages on the test as a temporary solution (long term solution would be ditching Cypress):
|
@mihhail-m I bet you meant playwright as an alternative |
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as abuse.
This comment was marked as abuse.
Actually, since Cypress is open source with MIT license, thus you are allowed to clone and manipulate the code, I would welcome if someone made changes to Cypress in form of a https://www.npmjs.com/package/patch-package file and posted it in this thread. pnpm users don't even need patch-package. Surely a feature that simple should not require too many files changed. |
This comment was marked as off-topic.
This comment was marked as off-topic.
I'm not sure if this is the right place to ask, but I'm hoping someone here might have had a similar experience and could offer some advice. I have cypress, allure reporter and cypress-fail-fast How can I ensure that all tests, regardless of their outcome, are included in the report? Any guidance would be appreciated! |
Current behavior:
All tests are run even if one fails.
Expected behavior:
Providing an option to abort the test suite as soon as a test fails.
How to reproduce the current behavior:
Make a test fail.
Environment
The text was updated successfully, but these errors were encountered: