kuceb / cypress-plugin-retries

A Cypress plugin to retry failed tests.
MIT License
237 stars 20 forks source link

Plugin seems to break test.state property in cy.state('runnable') of a test suite #18

Open proCrichard opened 5 years ago

proCrichard commented 5 years ago

When a test fails and is retried, that test's details in the cy.state('runnable') object is somehow broken. From an example I have here, I can see in the cypress logger that my test has failed:

Screen Shot 2019-07-30 at 1 13 50 PM

However the cy.state('runnable') output on that test considers it 'passed': Screen Shot 2019-07-30 at 1 15 19 PM

This is throwing off a plugin I use to report test results. Any information you have on this issue would be helpful.

kuceb commented 5 years ago

@proCrichard could you mention what plugin you are using?

proCrichard commented 5 years ago

I wrote a custom plugin to send test results to datadog.

Starts with an after hook:

after(() => {
  const findTests = suite => {
    suite.tests.forEach(test => {
      cy.task('logTestResults', {
        title: `${test.parent.title}${test.title}`,
        state: test.state,
      });
    });

    if (suite.suites.length < 1) {
      return;
    }
    suite.suites.forEach(nestedSuite => {
      findTests(nestedSuite);
    });
  };

  cy.state('runnable').parent.suites.forEach(suite => {
    findTests(suite);
  });
});

Which triggers this event listener:

const dogapi = require('dogapi');
const changeCase = require('change-case');

module.exports = (on, app) => {
  const dogapiOptions = {
    api_key: process.env.DATADOG_API_KEY,
    app_key: process.env.DATADOG_APP_KEY,
  };
  dogapi.initialize(dogapiOptions);

  on('task', {
    logTestResults({ title, state }) {
      const tags = [];

//This if statement is to catch state=undefined which is sent from tests that failed and were retried.
      if (!state) {
        state = 'failed';
      }

      tags.push(`outcome:${state}`);
      tags.push(`description:${changeCase.snakeCase(title)}`);
      tags.push(`app:${app}`);
      dogapi.metric.send(`app.e2e`, 1, { tags }, (error, results) => {
        console.dir(results); // eslint-disable-line no-console
      });
      return null;
    },
  });
};
kuceb commented 5 years ago

did your test that failed (but had state: passed) fail from a beforeEach hook or in the test body?

What retry number do you have enabled?

proCrichard commented 5 years ago

Retries set to 2 I had the same outcome when I forced a test to fail in:

kuceb commented 5 years ago

@proCrichard alright, and what version of cypress and this plugin?

I just added your after() to my spec for this project, and I am getting the correct state set on the runnables

proCrichard commented 5 years ago
"cypress": "3.4.0",
"cypress-plugin-retries": "1.2.2"
kuceb commented 5 years ago

@proCrichard ok, I think I am reproducing it now. Thanks

proCrichard commented 5 years ago

Ok great. I appreciate you jumping on this for me.

kuceb commented 5 years ago

@proCrichard after spending a couple hours on this, I'll need to edit the Cypress source directly to fix this, but I have a PR to do so here https://github.com/cypress-io/cypress/pull/3968

I would recommend using the module API to pull results out instead of using runnable instances. https://docs.cypress.io/guides/guides/module-api.html#cypress-run. However, I know that can be cumbersome