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".
Let's walk through why this is so hard to see.
You have two tests. Both create a contact named "Dana Fox".
Run the first alone: it passes. Run the second alone: it passes. Run them together: the second fails, because it expected one Dana Fox and found two.
Now it gets worse. When the team splits the suite across machines to save time, the failure moves around. Someone re-runs the build and it passes. Nobody can reproduce it.
The fix is to give each test its own data:
it('creates a contact', async function () {
const name = `Dana Fox ${Date.now()}`;
await driver.findElement(By.css('[data-testid="contact-name-input"]')).sendKeys(name);
await driver.findElement(By.css('[data-testid="save-contact"]')).click();
const rows = await driver.wait(async () => {
const found = await driver.findElements(By.xpath(`//*[contains(text(),'${name}')]`));
return found.length === 1 ? found : null;
}, 5000);
assert.strictEqual(rows.length, 1);
});
Date.now() gives the current time in milliseconds, so every run gets a different name. Two tests cannot collide, and neither can two runs of the same test.
About cleaning up. Deleting the data your test created is good practice. But never write a test that only passes because an earlier test cleaned up properly. Runs crash. Machines get stopped. A test that needs a perfectly clean database will fail one day for no clear reason.
A tip that saves a lot of time. Creating data by clicking through forms is slow and fragile. Selenium has no built-in HTTP client, so use a normal library like node-fetch or axios in your setup:
beforeEach(async function () {
await fetch('http://localhost:3000/api/contacts', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'Maya Chen', email: 'maya@lumina.io' }),
});
});
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.
Reference: Best practices.