I once watched two engineers spend a whole afternoon on a failing build. They read the app code, checked the database, and blamed the server. The real cause was two tests that both created a customer named "Test User".
This is one of the most confusing bugs you will meet, so let's walk through it slowly.
You have two tests. Both create a contact named "Dana Fox".
Run the first one alone: it passes. Run the second one alone: it passes. Run them together: the second one fails. It expected to find one Dana Fox and it found two.
Now it gets worse. On your machine the tests run in the same order every time, so it always fails the same way. On the build server the tests are split across machines, so sometimes the failure moves to a different test. Someone re-runs the build and it passes. Nobody can reproduce it.
The cause is simple. Both tests used the same name, so they got in each other's way.
The fix is to give each test its own data. The easiest way is to add something unique to the name:
it('creates a contact', () => {
const name = `Dana Fox ${Date.now()}`;
cy.get('[data-testid="contact-name-input"]').type(name);
cy.get('[data-testid="save-contact"]').click();
cy.contains('[data-testid="contact-row"]', name).should('exist');
});
Date.now() gives the current time in milliseconds, so every run gets a different name. Two tests cannot collide any more, and neither can two runs of the same test.
A note about cleaning up. It is good to delete the data your test created. But never write a test that only passes because an earlier test cleaned up properly. Runs crash halfway. Machines get stopped. If your test needs a perfectly clean database to pass, it will fail one day for no clear reason.
One more tip that will save you a lot of time. Creating test data by clicking through forms is slow and breaks easily. If your app has an API, create the data with a request instead:
beforeEach(() => {
cy.request('POST', '/api/contacts', { name: 'Maya Chen', email: 'maya@lumina.io' });
cy.visit('/');
});
This takes milliseconds instead of seconds, and a change to the contact form cannot break your setup.
Remember this: every test creates its own data, with a value no other test uses. Your test must pass when it runs alone, first, last, or at the same time as others.
Reference: Best Practices.