A card validation suite I inherited had eleven copies of the same test. Same steps, different card number. When the error message was reworded, I edited eleven blocks and missed one.
Selenium itself has nothing to help here, because it is a browser control library and not a test runner. Parameterisation comes from whatever runner you chose, which is worth knowing before an interview.
In JavaScript with Mocha, a loop is all you need:
const invalidCards = [
{ number: '4111111111111112', reason: 'fails the checksum' },
{ number: '1234567812345678', reason: 'is not a real card number' },
{ number: '411111111111', reason: 'is too short' },
];
describe('checkout rejects bad cards', () => {
invalidCards.forEach(({ number, reason }) => {
it(`rejects a card that ${reason}`, async () => {
await driver.get(`${baseUrl}/checkout`);
await driver.findElement(By.css('[data-testid="card-number"]')).sendKeys(number);
await driver.findElement(By.css('[data-testid="pay"]')).click();
await driver.wait(until.elementLocated(By.css('[data-testid="card-error"]')), 5000);
});
});
});
That produces three separate tests, not one test with a loop inside. The 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 one 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.
In other languages the runner provides this directly, and interviewers ask by name:
- TestNG (Java) uses
@DataProvider, a method returning an array of argument sets. - JUnit 5 uses
@ParameterizedTestwith sources such as@CsvSourceor@MethodSource. - pytest (Python) uses
@pytest.mark.parametrize.
All the same idea: describe the cases as data, generate one test per case.
For larger sets, keep the data in a file. CSV and JSON are the usual choices, and reading them is ordinary code rather than anything Selenium-specific:
const cards = require('./data/cards.json');
Two limits, because this is easy to overuse.
It multiplies runtime, and in Selenium that hurts more than elsewhere. Each browser test carries the cost of driver communication, and twenty datasets is twenty full browser tests. If the logic is pure calculation, a unit test covering twenty cases runs in milliseconds and is the right tool. Use the browser where the screen differs.
Do not hide different behaviour in a loop. If a case needs an extra step or a different assertion, write it separately rather than adding an if.
Remember this: the runner parameterises, not Selenium. One generated test per case, with the reason in the name.
Reference: Selenium test practices.