lecture 7 of 180 completed

One test, many datasets

Ten near-identical tests is a maintenance problem. Generate them from data, and keep each failure readable.

A card validation suite I inherited had eleven copies of one test. Same steps, different card number. When the error message was reworded, I edited eleven blocks and missed one.

Describe the cases as data and let one body handle all of them.

const invalidCards = [
  { number: '4111111111111112', reason: 'fails the checksum' },
  { number: '1234567812345678', reason: 'is not a real card number' },
  { number: '411111111111', reason: 'is too short' },
];

for (const { number, reason } of invalidCards) {
  test(`rejects a card that ${reason}`, async ({ page }) => {
    await page.goto('/checkout');
    await page.getByTestId('card-number').fill(number);
    await page.getByRole('button', { name: 'Pay' }).click();
    await expect(page.getByTestId('card-error')).toBeVisible();
  });
}

Notice what this produces: three separate tests, not one test with a loop inside. That difference matters.

Each case fails on its own. If the short-card case breaks, one test goes red and the others stay green. A loop inside a single test stops at the first failure and hides the rest.

The name says which case broke. "rejects a card that is too short" tells you the bug without opening the file. This is why the reason belongs in the data.

They run in parallel. Playwright distributes tests across workers. Twenty generated tests spread across four workers finish in roughly a quarter of the time. A loop inside one test cannot be split.

For larger sets, keep the data in a JSON file and import it:

import cards from './fixtures/cards.json';

for (const card of cards) {
  test(`rejects a card that ${card.reason}`, async ({ page }) => { /* ... */ });
}

Two limits, because this is easy to overuse.

It multiplies runtime. Twenty datasets is twenty browser tests. If what you are checking is pure calculation, a unit test covering twenty cases runs in milliseconds and is the right tool. Use the browser for cases where the screen differs.

Do not hide different behaviour in one loop. If a case needs an extra step or a different assertion, it is not the same test. Write it out rather than adding an if inside.

One Playwright-specific warning. Generate tests at the top level of the file, as above. Test titles have to be known before the run starts, so building them inside another test does not work.

Remember this: data in an array, one generated test per case, and the reason in the title.

Reference: Parameterize tests.