Skip to main content
Test Design5 min readQAEverest Team

Test case vs test scenario vs test script: the difference, with examples

Three terms that get used as if they meant the same thing. They don't. One login page worked through at all three levels, plus when to use each one and the mistakes that blur them.

A release meeting, one feature: the new login page. Someone asks whether it's covered.

One answer is "six scenarios". Another is "fourteen test cases". The pipeline dashboard shows "nine scripts, all green". All three are correct, and nobody in the room can say whether the login page is covered, because the three numbers count different things.

Test scenario, test case and test script are three of the most-used terms in QA, and they get used interchangeably. They aren't the same thing. Each one sits at a different level of detail and answers a different question. Once a team agrees on which is which, coverage conversations get much shorter.

This post explains the difference with one worked example: the login page of an online shop, taken from scenario to test case to script.

The short answer

  • A test scenario says what to test. It's one line, one situation that has to work.
  • A test case says how to check it: preconditions, test data, steps and an exact expected result.
  • A test script is a test case written so that a machine can run it, usually as automation code.

Each level adds detail to the one above it. One scenario usually becomes several test cases. A test case becomes a script only when it's worth automating.

Test scenarioTest caseTest script
AnswersWhat should we test?How exactly do we check it, and what should happen?How does a machine run that check?
Level of detailOne linePreconditions, data, steps, expected resultCode, with every expected result as an assertion
Usually writtenDuring story refinement and planningOnce the behaviour is agreedOnce the case is stable and worth running often
Main readersQA, product, developersTesters, reviewers, auditorsAutomation engineers and the CI pipeline
ExampleLogin is refused when the password is wrongWrong password for a registered email shows "Email or password is incorrect" and stays on the login page`await expect(page.getByText('Email or password is incorrect')).toBeVisible();`

Level 1: test scenarios

A test scenario is a situation the product has to handle, written as one line. It doesn't say how to test it. It says what has to be true.

Here are the scenarios for the shop's login page:

IDTest scenario
TS-01A registered user logs in with the correct email and password
TS-02Login is refused when the password is wrong
TS-03Login is refused when a required field is empty
TS-04An account is locked after repeated failed attempts
TS-05A user can reset a forgotten password from the login page
TS-06A logged-in session ends after the idle timeout

That list fits on a screen, and anyone can read it: a product manager, a developer or a new tester. That's what scenarios are for. They make it quick to ask "what's missing?" before anyone writes a step. Someone looking at this list might ask about logging in with Google, or about what happens on a phone. Those are new scenarios, and they cost one line each to add.

A good scenario has an outcome in it. "Test login" isn't a scenario, because there's nothing to check. "Login is refused when the password is wrong" is one, because you can tell whether it's true.

Level 2: test cases

A test case takes one way a scenario can play out and pins it down: the starting state, the exact data, each step, and what should happen.

One scenario usually has several. TS-02 ("login is refused when the password is wrong") has at least three that behave differently:

IDTest case
TC-02.1Wrong password for a registered email shows a generic error
TC-02.2The correct password typed in the wrong case is refused
TC-02.3A password entered for an unregistered email shows the same generic error

TC-02.3 is the kind of case a scenario alone won't surface. If the error for an unknown email differed from the error for a wrong password, the login page would tell anyone which email addresses have accounts. Finding cases like that is test design. It's the part of the work that needs a tester's judgement.

Here is TC-02.1 written out in full:

FieldValue
IDTC-02.1
ScenarioTS-02 Login is refused when the password is wrong
TitleWrong password for a registered email shows a generic error
PreconditionsAn active account exists for asha@example.com. The user is logged out.
Test dataEmail: asha@example.com. Password: Wrong-pass-1
PriorityHigh
StepActionExpected result
1Open the login pageThe form shows Email and Password fields and a Log in button
2Enter asha@example.com in EmailThe email is accepted as typed
3Enter Wrong-pass-1 in PasswordThe characters are masked
4Select Log inThe message "Email or password is incorrect" appears. The user stays on the login page. The Password field is empty.

Two things make this a test case rather than a longer scenario. First, anyone who runs it uses the same data and does the same thing. Second, the expected result is exact. "An error appears" would let two testers pass two different behaviours. "Email or password is incorrect, user stays on the page, password cleared" doesn't.

Level 3: test scripts

A test script is a test case turned into instructions a machine can follow. Here is TC-02.1 as a Playwright test:

```typescript import { test, expect } from '@playwright/test';

// TC-02.1 Wrong password for a registered email shows a generic error test('TC-02.1 wrong password shows a generic error', async ({ page }) => { // Step 1: open the login page await page.goto('https://shop.example.com/login');

// Steps 2 and 3: enter the email and the wrong password await page.getByLabel('Email').fill('asha@example.com'); await page.getByLabel('Password').fill('Wrong-pass-1');

// Step 4: select Log in await page.getByRole('button', { name: 'Log in' }).click();

// Expected result: one assertion for each part of it await expect(page.getByText('Email or password is incorrect')).toBeVisible(); await expect(page).toHaveURL(/login/); await expect(page.getByLabel('Password')).toHaveValue(''); }); ```

Look at the last three lines. Every expected result in the test case became an assertion in the script. That's why the test case matters even when the script exists. If the case had said "an error appears", the script would have had nothing exact to check, and it could pass while the page showed the wrong message.

"Test script" has two meanings

You'll see the term used in two ways, so it's worth knowing both:

  • In most teams today, a test script means automation code, like the Playwright test above.
  • In older standards and in manual testing, a test script can mean any detailed, step-by-step procedure, including one a person follows. "Scripted testing" in that sense is the opposite of exploratory testing, not of manual testing.

When someone says "script", check which one they mean before you count anything.

Why Gherkin blurs the line

Teams that write tests in Gherkin (Given / When / Then) have an extra source of confusion. In Gherkin, the keyword `Scenario` holds what this post calls a test case: concrete steps, concrete data and an expected outcome.

Here is TC-02.1 in Gherkin:

```gherkin Feature: Login

Scenario: Wrong password for a registered email shows a generic error Given an active account exists for "asha@example.com" And the user is logged out When the user logs in with "asha@example.com" and password "Wrong-pass-1" Then the message "Email or password is incorrect" is shown And the user stays on the login page And the password field is empty ```

And all three TS-02 cases as one `Scenario Outline`, with one row of data per case:

```gherkin Scenario Outline: Login is refused with a generic error Given an active account exists for "asha@example.com" with password "Shop-pass-1" When the user logs in with "<email>" and password "<password>" Then the message "Email or password is incorrect" is shown

Examples:

caseemailpassword
TC-02.1asha@example.comWrong-pass-1
TC-02.2asha@example.comSHOP-PASS-1
TC-02.3nobody@example.comShop-pass-1

```

Gherkin keywordWhat it is in the terms above
`Feature`A group of related scenarios, such as "Login"
`Scenario`A test case with steps and an expected result
`Scenario Outline` with `Examples`A test case template, run once per data row. Each row is effectively its own test case.
`Given`Preconditions
`When`The steps
`Then`The expected result

So when a BDD team says "we have forty scenarios", they usually mean forty test cases. Neither usage is wrong. The fix is to agree on one vocabulary for the team and use it in every report.

When each one earns its place

Test scenarios are the right tool when you're deciding what to test:

  • Story refinement and sprint planning, before the behaviour is fully agreed
  • Checking coverage against a requirement: is every rule in the story covered by at least one scenario?
  • A charter for an exploratory session
  • A quick estimate of testing effort

Test cases are the right tool when a check has to be repeatable:

  • Regression testing, where different people need to run the same check the same way
  • Evidence for auditors, customers or a release decision
  • Onboarding: a new tester learns the product from well-written cases
  • The basis for automation, because a script can only be as exact as the case behind it

Test scripts are worth writing when a check runs often and doesn't need human judgement:

  • Critical flows that should run on every build
  • Checks that repeat across many data combinations or browsers
  • Stable features whose behaviour isn't changing this sprint

Scripts are a poor fit for a screen that's being redesigned this month, a check you'll run once, or anything that needs a person to judge it, such as "is this message clear?" or "does this layout look right?". Deciding which cases deserve automation is a QA call, made one case at a time.

Six mistakes that blur the three

  1. Adding the counts together. "Six scenarios, fourteen cases and nine scripts" is three measurements, not twenty-nine tests. Report coverage at one level and say which level it is.
  2. Scenarios with no outcome. "Test the login page" can't pass or fail. Write the situation and what has to be true.
  3. Expected results that say "works as expected". A tester can't verify that, and a script can't assert it. Name the exact message, state or value.
  4. Test cases tied to the layout. "Click the blue button at the top right" breaks when the design changes. "Select Log in" doesn't. Be exact about data and outcomes, not about where things sit on the screen.
  5. Scripts with no test case behind them. When a script like that fails, nobody can say what behaviour it was meant to protect. Name each script after the case it runs, for example `TC-02.1`.
  6. Treating automation as the finish line for every case. Some cases are cheaper to run by hand, and some need a person's eyes. A healthy suite has both.

How the three connect

The levels form a chain:

Requirement → Scenarios → Test cases → Scripts

When each link names the one above it, the hard questions get quick answers. Each script carries its test case ID, each case names its scenario, and each scenario points to the requirement it comes from. Which requirement has no scenario? Which scenario has no test case? Which test case is automated, and which still runs by hand? When a script fails, which requirement is at risk?

Without the chain, the numbers in the release meeting stay incomparable. With it, "is the login page covered?" has one answer.

Where QAEverest fits

QAEverest works across all three levels, with your QA team reviewing each step:

  • Test cases from requirements. It turns a user story or requirement into test cases with Given/When/Then steps, test data and a category, ready for your team to review and edit.
  • Test cases that run as automation. Reviewed UI test cases can run in a browser as automation, without a hand-written script first.
  • Scripts in your own framework. When your team wants the code, a UI run can be exported as Selenium (Java), Cypress (JavaScript or TypeScript) or Playwright (TypeScript or Python). Code export is enabled on request.

Deciding which scenarios matter, what the right expected result is and which cases are worth automating stays with your QA team.

A scenario says what to test. A test case says how to test it, with which data, and what should happen. A script makes a machine do it on every build. Get the middle level right and the other two get easier: the scenario becomes something you can check, and the script has something exact to assert.

See it on your own stories

1000+ free credits on signup, no card required — roughly 100 test-case generations before you pay for anything.

Start free