0

We use Cypress for test automation, but sometimes tests get stuck in Jenkins due to some issue, and the whole execution gets stuck.

How can I make Cypress skip a test if its execution takes really long time. Let's say make it skip after 15 min, but the rest suit execution should continue.

I couldn't find anything for this issue. I have seen some ideas about cancelling the whole suite if one test fails, but that's not what I need.

3 Answers3

1

There is a timeout option on the Mocha context, which you can use in your Cypress tests because Cypress is built on top of Mocha.

Before the problem tests, add this command

beforeEach(function() {
  this.timeout(60_000)      // timeout when stuck
})

Or for every test, add it in the /cypress/support/e2e.js file.

Reference: How to set timeout for test case in cypress

Also Mocha timeouts, can be used at suite level, test level and hook level.

describe('a suite of tests', function () {
 this.timeout(500);

 it('should take less than 500ms', function (done) {
   setTimeout(done, 300);
 });

 it('should take less than 500ms as well', function (done) {
   setTimeout(done, 250);
 });
})

Alternatively, you can try the done() method which signals the end of a test has been reached.

it('gets stuck and needs a kick in the ...', (done) => {

  // my sticky test code

  cy.then(() => done())  // fails the test if never called

})
W.Moura
  • 31
  • 3
0

You could use the standard setTimeout() function in the beginning of each test. All it does is execute a function after a period of time. If the function it executes throws an exception cypress will catch that, fail the test, and move on.

So you can setTimeout() before the test, then clearTimeout() after the test, then you effectively have a test timeout feature.

const testTimeout = () => { throw new Error('Test timed out') };

describe('template spec', () => {
  let timeout;

  beforeEach(() => {
    // Every test gets 1 second to run
    timeout = setTimeout(testTimeout, 1000);
  });

  afterEach(() => {
    // Clear the timeout so it can be reset in the next test
    clearTimeout(timeout)
  });

  it('passes', () => {
    cy.wait(500);
  });

  it('fails', () => {
    cy.wait(1500);
  });
});

If you wanted to handle this at an individual test level:

const testTimeout = () => { throw new Error('Test timed out') };

it('fails', () => {
  // Start timeout at beginning of the test
  const timeout = setTimeout(testTimeout, 1000);

  // Chain clearTimeout() off the last cypress command in the test
  cy.wait(1500).then(() => clearTimeout(timeout));

  // Do not put clearTimeout() outside of a cypress .then() callback
  // clearTimeout(timeout)
});

You need to call clearTimeout() in a chained .then() off the last cypress command. Otherwise the timeout will actually be cleared immediately because cypress commands are asynchronous.

With all that said, I'll also leave you with Mocha's docs on the this.timeout() feature. In all honestly, I couldn't get it to work the way I expected, so I came up with the setTimeout() method https://mochajs.org/#test-level. Hopefully one of these helps.

DJSDev
  • 812
  • 9
  • 18
-2

Cypress has timeout configuration option. If a command takes longer, its will automatically fail

it('test', () => {
  cy.wait(1000); 
  // ...
})

If you want to skip test which failed with timeout, you can use try/catch

try {
    cy.wait(1000); 
    //...
} catch (e) {
    ....
}
rycha
  • 679
  • 2
  • 9
  • so, this timeout should be added to every test, right? Is there a way to make config changes to apply to all tests instead? – FeelLuck Feb 15 '23 at 18:16
  • You can add defaultCommandTimeout in cypress.json and create function to which you can pass test to catch error. And reuse this function – rycha Feb 15 '23 at 18:20
  • Thanks for idea! Sorry if my questions look stupid, but could you please clarify how the test body should look like? describe(() => { it(..., () => { try{ cy.timeout(1000) } catch (e) { // test body ? } }) }) and what's the code for skipping? – FeelLuck Feb 15 '23 at 18:27
  • Is this a custom command? Can you link to the documentation for this command? – DJSDev Feb 15 '23 at 18:37
  • sorry i meant cy.wait – rycha Feb 15 '23 at 18:42
  • 1
    @rycha, I think cy.wait() would not help here... I don't need it to wait :( – FeelLuck Feb 15 '23 at 18:55
  • wait works in same way how I said, look at docs https://docs.cypress.io/api/commands/wait#Timeouts – rycha Feb 15 '23 at 19:01
  • as I get it, wait() is used for a specific command/action to kinda wait for the element to appear on the page or loading completed. We use it often in our tests. So, if an element is not found, the test would fail. While I need to skip a test in CI if for some reason execution would stuck.. kinda hung test. They get stuck in CI (and only in CI) for unknown reason. So, if that happens, then ideally this test should be skipped, not keeping the job stuck – FeelLuck Feb 15 '23 at 20:30
  • Stop, try to replace wait method from my example with your test which stuck. And this test should have timeout option in config, try to find in docs – rycha Feb 15 '23 at 20:40
  • But i think problem might be generally with test)) why you want to pass test if he didnt find element? If element wasnt to be found, just change test) – rycha Feb 15 '23 at 20:45
  • This is not about finding elements. Random tests from random suites get stuck. No errors/exceptions thrown. Just smth happens with Cypress in CI and tests load indefinite time.. What I want is to have a kind of cypress config for the whole suite, which would say to skip a test if it gets stuck for any reason for more that let's say 15 min. Currently tests being marked as timed out without any logs.. And Cypress doesn't execute the rest of the suite if the first test stuck. – FeelLuck Feb 16 '23 at 18:46