Most test plans fail at the scope section, and they fail quietly. Someone writes "this release covers the billing changes" and moves on, and three weeks later a customer finds that invoice PDFs stopped rendering for accounts on annual terms. Nobody tested it. Nobody decided not to test it either, which is the real problem, because those two outcomes look identical the morning after and only one of them can be defended.

A test plan template does not make you better at testing. What it does is force a decision at each section that would otherwise be made by default, and the first of those decisions is what you are deliberately leaving alone. This guide gives you the eight sections, a worked example for a billing release, a UAT variant, and a copy-paste template at the bottom.

In this article

1.

2.

3.

4.

5.

6.

7.

8.

9.

10.

11.

8sections in the template
1page for a normal release
3 minto read it cold on release day

What a Test Plan Template Actually Has to Do

A test plan is the written agreement about what gets verified before a release ships, and what happens if it does not pass. It exists so that the engineer who built the change, the person running the tests, and whoever has to answer the customer afterward all hold the same picture of what was covered.

Three things it is not, and each confusion produces a different useless document:

  • It is not a list of test cases

    The plan says which areas get covered and to what depth. A test case says click this, enter that, expect this result. Mixing them produces a forty-page document that nobody reads before a release and nobody updates after one. Keep the cases in a test case template or your test management tool, and let the plan stay readable.

  • It is not a schedule

    Dates belong in the release ticket, where they change without anyone needing to reopen a document. A plan that contains a Gantt-shaped timeline is stale within a week, and once one section of a document is visibly wrong, readers stop trusting the rest of it.

  • It is not a permanent artifact

    Write it per release, keep it with the release, and let it die when the release ships. The thing that carries forward is the regression set and the standing decisions in the approach section, not the document. Teams that maintain one eternal test plan end up with a file that describes a product from two years ago.

The Eight Sections of a Test Plan

Eight sections, in this order. The order matters. Scope sits above environment because you cannot size the environment until you know what you are covering, and exit criteria sit above the approach so that the tests are chosen to satisfy a stated bar rather than the bar being written afterward to match whatever the tests happened to produce.

  1. 1

    1. Header: release, owner, status, date

    One line each, plus a link to the release ticket. The status field earns its place: draft, in review, agreed, in progress, or signed off. A surprising share of release-day confusion is one person reading a draft plan as though it had been agreed, and a single word at the top removes it.

  2. 2

    2. Scope, in and out

    Two lists. What this release changes and therefore gets tested, and what is explicitly not being tested this time. The second list is the one with all the value in it. "Payment provider webhooks are out of scope because nothing in this release touches them" is a decision somebody can challenge before the release rather than an omission somebody discovers after it.

  3. 3

    3. Environment and test data

    Which environment, on which build, with what data. Name the accounts or fixtures you will use, including the awkward ones: the account with five years of history, the one on the legacy plan, the one in a non-default timezone. Most released defects that "could not be reproduced in staging" trace back to this section being written as "staging" and nothing else.

  4. 4

    4. Entry and exit criteria

    Entry criteria are what must be true before testing starts: the build is deployed, the migrations have run, the feature flag is on. Exit criteria are what must be true to ship, stated as numbers rather than adjectives. No open critical defects, fewer than five open majors, ninety percent of the regression set passing. If you track QA metrics like defect density or escaped defects, this is where the target belongs, next to the current number rather than floating on a dashboard.

  5. 5

    5. Test approach and types

    Which kinds of testing you are running and why: functional on the new behavior, regression on the surrounding areas, exploratory where the risk is highest, integration across the boundary this release moved, and UAT if a business user has to accept it. Say what you are automating and what stays manual this time. The honest version of this section usually admits that the automation covers the stable parts and the humans cover the new part, which is the correct arrangement and is worth writing down.

  6. 6

    6. The regression set

    The specific behaviors outside this change that must still work. Not "run the suite". A named list, ordered by what has actually broken before. This is the section that separates a plan that catches real problems from one that produces a green check mark, and the next section of this guide is about where the list comes from.

  7. 7

    7. Risks and mitigations

    Three or four, each with what you will do about it. Thin coverage in an area, a dependency that landed late, a test environment that does not have production-shaped data, one person who is the only one who understands the flow. Writing a risk down converts it from a surprise into a decision, and about half of them get mitigated simply because somebody read the line.

  8. 8

    8. Roles and sign-off

    Who tests what, and the single name who says it ships. Sign-off by committee means sign-off by nobody, and the failure mode is well documented: everyone assumes somebody else checked the thing that was in nobody's column. One name, one date, recorded on the plan.

Test Plan vs Test Strategy Document vs Test Case

Three artifacts that get conflated, three different lifespans. Most teams under a hundred people need one of them and borrow a paragraph from the second.

  • Test strategy document: how we test, in general

    Organization-level and long-lived. Tooling, environments, levels of testing, what gets automated, who owns quality, how defects are classified. It changes once or twice a year. If your team has three standing decisions rather than thirty, fold them into the approach section of the plan and skip the separate document, because a strategy nobody rereads is just a file.

  • Test plan: what we are testing this time

    Per release or per project, and short-lived by design. Scope, environment, criteria, regression set, sign-off. This is the document the template on this page is for, and for most software teams it is the only one of the three that earns its maintenance.

  • Test case: exactly how one thing gets checked

    Steps, data, expected result. These live in the test management tool or the automation suite, not in the plan. The plan references areas, and the cases implement them. A plan that inlines its cases has confused the map with the territory and will be abandoned by the third release.

A regression set built from what is easy to automate tests the parts that were already stable. A regression set built from what broke for customers tests the parts that break.

Test Plan Example: A Billing Release

Structure advice is easy to agree with, so here is the shape filled in. This is compressed, but the proportions are right. Scope and the regression set take more room than the approach does.

Header. Release 4.12, annual billing terms. Owner: M. McGarvey. Status: agreed. Updated: July 31, 2026. Ticket: REL-412.

Scope, in. New annual term selection at checkout. Proration when switching from monthly to annual mid-cycle. Invoice PDF generation for annual terms. The billing settings panel changes. Webhook handling for the new subscription events.

Scope, out. Payment method management, unchanged this release. Tax calculation, unchanged. The dunning emails, which are owned by a different team and ship separately. Refunds, deliberately not covered because no code path in this release touches them, and if that turns out to be wrong the plan is wrong and we want to find that out now.

Environment and test data. Staging on build 4.12.3, against the sandbox payment provider. Five accounts: a new account with no history, an existing monthly account mid-cycle, an account with a past failed payment, an account on the legacy plan from before the pricing change, and an account in UTC+13 because the proration math crosses a date boundary there and has before.

Entry criteria. Build deployed to staging, migrations run, sandbox provider reachable, the annual flag on for the five test accounts.

Exit criteria. No open critical defects. No more than three open majors, each with a written decision to ship or hold. All eleven regression items passing. Invoice PDF verified by eye for two of the five accounts, because the rendering failure mode is visual and no assertion catches it.

Approach. Functional testing on the five new flows, manual. Regression on the list below, mixed automated and manual. Exploratory session of ninety minutes focused on the mid-cycle switch, which has the most branches. Integration testing on the webhook handler against replayed provider events. No UAT, because there is no external acceptance gate on this release.

Regression set. (1) Monthly checkout still completes. (2) Invoice PDF renders for monthly accounts. (3) Invoice PDF renders for accounts with a legacy plan, which broke in 4.9. (4) Cancellation mid-cycle still prorates. (5) Failed payment still triggers the retry schedule. (6) The billing panel loads for accounts with no subscription. (7) Currency displays correctly for non-USD accounts, which broke in 4.7 and was reported by three customers. (8) Seat count changes still bill correctly. (9) The receipt email still sends. (10) The provider webhook still handles the events it handled before. (11) Downgrade to the free tier still works.

Risks. The sandbox provider does not reproduce real proration rounding, so we will verify one real charge in production immediately after deploy. Only one engineer understands the invoice renderer, and they are out on the second day of testing, so their review moves earlier. The UTC+13 account is a fixture rather than a real customer, so timezone coverage is thinner than it looks.

Sign-off. Testing by J. Rivera and the release engineer. Ship decision by M. McGarvey, on release day.

Notice items 3 and 7 in the regression set. Neither is part of this release, and neither would be chosen by looking at the diff. They are there because they broke before, for identifiable customers, and that is the only reason a regression set is worth more than a suite run.

User Acceptance Testing Template

A user acceptance testing plan is the same document with three fields changed. The testers are the people who will use the software, the criteria are written in business language, and the output is a go or no-go rather than a defect count.

  1. 1

    Scenarios, not features

    Write end-to-end journeys in the user's words. "Close the month and export the summary for the finance team" rather than "test the export button". A feature list invites clicking around, and clicking around produces feedback about spacing rather than a verdict on whether the work can be done.

  2. 2

    Real data, real roles

    UAT on synthetic data finds almost nothing, because the interesting failures live in volume, in odd historical records, and in permission boundaries. Use a production-shaped copy and give each tester their actual role, not an admin account, since the admin account hides every permission defect you have.

  3. 3

    Acceptance criteria in business language

    Each scenario ends with a statement the business owner can judge without asking an engineer what it means. "The exported summary matches the finance team's current spreadsheet for last month" is testable by the person who owns the outcome. "The export endpoint returns 200" is not their question.

  4. 4

    One named approver and a decision

    UAT ends in a decision, recorded with a date and a name. Go, go with known issues listed, or no-go with the specific scenarios that failed. A UAT phase that ends with "mostly fine" has not ended.

Where the Test Plan Fits in the QA Process

The plan is the second step in a QA process, and it sits between two things that determine whether it is any good.

  1. 1

    Before: what changed and what it touches

    Requirements and the diff. If your team writes a PRD, its requirements section is the raw material for the scope list, and its non-goals are the raw material for the out-of-scope list. Skipping this step is what produces plans that test the happy path of the new feature and nothing around it.

  2. 2

    The plan: scope, criteria, and the regression set

    The document on this page. Half an hour for a normal release when the inputs exist, most of a morning when you have to reconstruct them.

  3. 3

    Execution: cases, sessions, and defect logging

    Cases run, exploratory sessions timeboxed, defects logged against a bug tracking template so they carry enough detail to be actionable. This is where a weak plan shows up as testers asking what they are supposed to be checking.

  4. 4

    Triage: which defects hold the release

    Every defect gets a severity and a priority, and those are two different things. Our guide to bug severity vs priority covers the distinction, and the defect management process covers the lifecycle after logging. The exit criteria you wrote in section four are what make this conversation short.

  5. 5

    After: sign-off, release notes, and the loop back

    Sign-off recorded, release notes written from what actually shipped, and anything that escaped to production fed back into the regression set for next time. A defect that escapes twice is a process finding, not bad luck, and it usually warrants a root cause analysis.

The QA Checklist Before Sign-Off

Run this before you call a release tested. It takes about three minutes and catches the failures that are embarrassing to find afterward.

Before you sign off

  • The out-of-scope list exists and somebody other than the author has read it.
  • Every exit criterion is a number, not an adjective.
  • The test data includes at least one awkward account, not only fresh fixtures.
  • The regression set names specific behaviors, not "the existing suite".
  • At least two regression items came from defects that reached real customers.
  • Every open defect above minor has a written ship or hold decision against it.
  • Someone in support has read the scope and did not flag a fragile area you left out.
  • The customers who reported the defects this release fixes are identified, and someone owns telling them.
  • One named person has signed off, with a date.

The last three are the ones that fail, and the final two fail for a structural reason rather than a discipline one.

Where the Regression Set Comes From

Writing a test plan is a half-hour job. Building a regression set that is worth running is not, and the difference between the two is almost entirely whether anyone can tell you what has broken for customers recently.

Ask a team how their regression suite was assembled and the honest answer is usually that it grew. Someone automated the flows that were easy to automate, then added a case each time a bad release made somebody angry enough to remember. What that produces is thorough coverage of the stable parts of the product and thin coverage of exactly the areas that keep failing, because the failures that hurt most were reported by customers to support and never made it back into engineering's picture of risk.

The version of this that works is mechanical, and it depends entirely on whether a link was recorded when the defect was first reported:

  • Start from the tickets, not the code

    Before writing the regression section, pull the defects reported by customers in the areas this release touches, over the last two or three releases. You are not looking for open defects. You are looking for the ones you already fixed, because a fixed area that was fragile once is the highest-yield place to spend a regression item.

  • Count accounts, not reports

    One customer reporting the same rendering problem nine times is a different signal from nine customers reporting it once each, and a raw count hides which one you have. The second belongs in the regression set permanently. The first might be one unusual configuration.

  • Keep the customer's description of the failure

    A regression item written as "invoice rendering" is not testable. Written as "annual invoices for accounts on the legacy plan render with an empty line items table", it is, and that sentence almost always exists already in the words of the person who reported it. Paraphrasing sands off the specifics, and the specifics are the test.

  • Note who is still waiting

    Any defect this release fixes belongs to somebody who reported it and has not been told. Capturing that list while you write the plan costs nothing and turns writing the release notes into a short job instead of an archaeology exercise.

A regression set that catches things

  • Built from defects that reached real customers
  • The original description of the failure is one click away
  • You can see how many accounts hit each one
  • The fixes in this release map to the people waiting on them
  • Support reads the scope and recognizes the risky areas

A regression set that goes green

  • Built from whatever was easiest to automate
  • The original wording is in a closed ticket nobody searches
  • Counts get estimated from memory
  • Nobody knows who reported what
  • Support sees the release notes at the same time as customers do

That table is not really about testing. It is about whether the handoff from support to engineering left a durable trail behind it, and the test plan is one of several moments a team finds out that it did not. The same gap turns up when someone tries to write the problem section of a PRD and cannot reconstruct who asked, and it is the same reason closing the customer feedback loop is the step that quietly gets skipped.

For teams where support runs on HubSpot Service Hub and engineering runs on Linear, IssueLinker is what keeps that trail intact. A ticket becomes a linked Linear issue in one click with the customer's own wording carried over, and the two stay in sync in both directions, so when you sit down to build a regression set the history of what broke and who it broke for is already attached to the work. The Linear HubSpot integration guide covers how the two-way sync works, and how to get bugs fixed faster covers the handoff itself.

Build the regression set from real tickets

If support runs on HubSpot Service Hub and engineering runs on Linear, IssueLinker links the customer ticket to the engineering issue and syncs both ways, so the history of what broke and who reported it is still there when you write the next test plan.

Mistakes That Make a Test Plan Ignored

Four patterns account for most plans that get written, circulated, and never opened again.

  • Exit criteria written as adjectives

    "Testing complete and quality acceptable" cannot be evaluated, and everyone in the room knows it while agreeing to it. Criteria need numbers: how many open defects at which severities, what share of the regression set passing, which specific items are mandatory. Adjectives push the argument to release day, when the pressure is highest and the judgment is worst.

  • No out-of-scope list

    A plan that lists only what is covered implies everything else was considered, which is never true. The omission is invisible until something breaks in an uncovered area, and then the conversation is about whether anyone thought about it at all. Two lines of out-of-scope prevent that entirely.

  • Test data that does not resemble production

    Fresh fixtures pass. Real accounts have five years of history, deleted users, a legacy plan, an unusual timezone, and one field somebody filled with an emoji in 2023. Almost every defect that "could not be reproduced" is a test data finding, and the fix is to name the awkward accounts in section three rather than to write "staging".

  • A regression set assembled from the diff

    Testing what changed is necessary and not sufficient. The defects that reach customers usually live one step away from the change, in an area that shares a code path nobody remembered. That is why the regression set is built from failure history rather than from the pull request.

The thread through all four is that a test plan is a risk document and gets judged as one. The measure is not whether it is thorough. It is whether someone reading it on release day can say what was covered, what was not, and why that was the right call.

Copy-Paste Test Plan Template

Here is the template in plain text. Paste it into a doc, a Notion page, the description of the release ticket, or wherever your team keeps this. Delete a section when it genuinely does not apply rather than writing "N/A", except for the out-of-scope list, which you should always fill in.

TEST PLAN: [ release or project name ]

Owner:        [ name ]
Status:       [ draft | in review | agreed | in progress | signed off ]
Updated:      [ date ]
Release:      [ link to the release ticket or epic ]


SCOPE, IN
- [ Area or flow this release changes, and therefore gets tested ]
- [ ... ]

SCOPE, OUT
- [ Area we are deliberately not testing, and why ]
- [ ... ]


ENVIRONMENT AND TEST DATA
Environment:  [ which environment, which build ]
Dependencies: [ sandbox providers, feature flags, seeded state ]
Accounts:
- [ A fresh account with no history ]
- [ An account with years of real-shaped history ]
- [ An account on a legacy plan or old pricing ]
- [ An account that hits an edge: timezone, currency, volume, permissions ]


ENTRY CRITERIA
- [ What must be true before testing starts ]
- [ ... ]

EXIT CRITERIA
- [ Open critical defects: 0 ]
- [ Open major defects: fewer than N, each with a ship or hold decision ]
- [ Regression set: N of N items passing ]
- [ Any check that must be done by eye rather than by assertion ]


APPROACH
Functional:   [ what, manual or automated ]
Regression:   [ what, manual or automated ]
Exploratory:  [ where the risk is highest, and how long a session ]
Integration:  [ which boundaries this release moved ]
UAT:          [ required or not, and who accepts ]


REGRESSION SET
1. [ A specific behavior outside this change that must still work ]
2. [ Something that broke before, for real customers, with their wording ]
3. [ ... ]

Source of items 2 and 3: [ link the original tickets or linked issues ]


RISKS
- [ Risk ] -> [ what we will do about it ]
- [ ... ]


ROLES AND SIGN-OFF
Testing:      [ names, and which areas each owns ]
Sign-off:     [ one name ]
Decision:     [ go | go with known issues, listed | no-go ]  on [ date ]

Customers waiting on fixes in this release:
- [ Who reported what, and who is telling them it shipped ]

The last block is the one that gets cut when a release runs late, and it is the one that turns a shipped fix into goodwill. The people who reported those defects are the reason several of your regression items exist. A test plan that draws on their reports and ends without anyone replying to them has left the cheapest part of the work undone.

Frequently Asked Questions