EthicsComputerCourses
Join training +91 90532 10052

Test Plans & Strategy

Software Testing · Lesson 13 of 30 Intermediate 6 min read Updated

Testing without a plan turns into clicking around until the deadline. A test plan says what will be tested, how, by whom, when and how you will know you are done. A test strategy describes the general approach an organisation or product follows across many projects. Both exist so that the whole team agrees on scope and risk before the pressure of a release.

In this lesson you will learn what goes into a test plan, how risk-based testing decides where to spend effort, how to estimate test effort, and how to track progress with a few simple metrics.

Test strategy and test plan

Test strategyTest plan
ScopeOrganisation, product line or programmeOne project, release or sprint
ChangesRarelyFor every release
AnswersWhat kinds of testing do we always do, with which tools and standards?What exactly will we test in this release, by when and by whom?
Example content"Every API has automated contract tests; UI tests use Playwright""Release 4.2 adds UPI autopay; three testers, 10 working days"

Small teams often merge the two into one living document or a wiki page. That is fine; what matters is that the decisions are written down and agreed.

What goes into a test plan

Older projects followed the IEEE 829 template; its successor, the ISO/IEC/IEEE 29119-3 standard, describes similar content. You do not need to follow a standard word for word. A practical plan covers:

YAML
test_plan: Release 4.2 - Kirana Kart mobile app
objectives: Confirm UPI autopay and the new cart work for real shop owners
scope:
  in: [UPI autopay setup, cart, invoice with GST, Android app]
  out: [iOS app (next release), admin reports]
approach:
  levels: [unit, integration, system, acceptance]
  types: [functional, regression, performance smoke, security basics]
  automation: Regression suite in pytest and Playwright, run on every merge
environment: Staging server, Android 13-15 devices, sandbox payment gateway
entry_criteria: Build deployed to staging and smoke tests passing
exit_criteria: 95% of planned tests passed, no open Critical or P1 bugs
schedule: 10 working days from build handover
team: [Priya (lead), Kabir, Isha]
risks:
  - Payment sandbox may be unstable; mitigation is a stub for non-payment tests
deliverables: [test cases, daily status, bug reports, summary report]

Each line answers a question someone will otherwise ask in a panic later: "Was iOS in scope?", "Which devices?", "When are we done?". Entry and exit criteria were introduced in SDLC & STLC.

Risk-based testing

You never have time to test everything equally, so spend effort where failure would hurt most. Risk-based testing rates each product risk by likelihood (how likely is a defect here?) and impact (how bad would a failure be?), multiplies them into a score, and tests the highest scores most thoroughly and earliest.

PythonRun it yourself
risks = [
    ("UPI payment fails or double-charges", 4, 5),
    ("Wrong GST on invoice", 3, 4),
    ("Search returns slow results", 3, 2),
    ("Profile photo upload fails", 2, 2),
    ("Order tracking map misplaces pin", 2, 3),
]

print(f"{'Risk':<38}{'L':>2}{'I':>3}{'Score':>7}  Test depth")
for name, likelihood, impact in sorted(risks, key=lambda r: r[1] * r[2], reverse=True):
    score = likelihood * impact
    depth = "Thorough" if score >= 12 else "Standard" if score >= 6 else "Light"
    print(f"{name:<38}{likelihood:>2}{impact:>3}{score:>7}  {depth}")
Output
Risk                                   L  I  Score  Test depth
UPI payment fails or double-charges    4  5     20  Thorough
Wrong GST on invoice                   3  4     12  Thorough
Search returns slow results            3  2      6  Standard
Order tracking map misplaces pin       2  3      6  Standard
Profile photo upload fails             2  2      4  Light

Likelihood rises with new or complex code, many recent bugs (remember that defects cluster) and inexperienced teams. Impact rises with money, legal duties, safety and the number of users affected. The scores are judgements, so agree them as a team; the value lies in the discussion as much as the numbers.

Estimating test effort

Managers will ask "how long will testing take?". A simple and widely used method is the three-point estimate: for each task, estimate an optimistic (O), most likely (M) and pessimistic (P) duration, then combine them as (O + 4M + P) / 6. The weighting pulls the result towards the most likely value while still allowing for things going wrong.

PythonRun it yourself
tasks = {
    "Write test cases": (3, 5, 10),
    "Set up test environment": (1, 2, 6),
    "Run functional tests": (4, 6, 9),
    "Regression and retesting": (2, 3, 7),
}

total = 0
for task, (optimistic, likely, pessimistic) in tasks.items():
    estimate = (optimistic + 4 * likely + pessimistic) / 6
    total += estimate
    print(f"{task:<26} {estimate:4.1f} days")
print(f"{'Total':<26} {total:4.1f} days")
Output
Write test cases            5.5 days
Set up test environment     2.5 days
Run functional tests        6.2 days
Regression and retesting    3.5 days
Total                      17.7 days

Other approaches include using data from similar past releases and, in agile teams, estimating together in story points. Always remember to include time for retesting fixed bugs and for regression runs, which beginners forget.

Monitoring and control

Once execution starts, the test lead compares progress with the plan every day (monitoring) and adjusts when things slip (control): moving people, cutting low-risk tests or asking for more time. A few metrics are enough for most projects:

  • Execution progress: tests run out of tests planned.
  • Pass rate: passed out of executed.
  • Defects: open bugs by severity and priority, found and fixed per day.
  • Blocked tests: tests that cannot run because of environment or bugs.
JavaScriptRun it yourself
const planned = 240;
const days = [
  { day: "Mon", executed: 45, passed: 38 },
  { day: "Tue", executed: 52, passed: 47 },
  { day: "Wed", executed: 40, passed: 36 },
  { day: "Thu", executed: 48, passed: 45 },
];

let executed = 0;
let passed = 0;
for (const d of days) {
  executed += d.executed;
  passed += d.passed;
  const progress = ((executed / planned) * 100).toFixed(0);
  console.log(`${d.day}: executed ${executed}/${planned} (${progress}%), pass rate ${((passed / executed) * 100).toFixed(1)}%`);
}
const perDay = executed / days.length;
console.log(`Days needed for the remaining ${planned - executed} tests: ${Math.ceil((planned - executed) / perDay)}`);
Output
Mon: executed 45/240 (19%), pass rate 84.4%
Tue: executed 97/240 (40%), pass rate 87.6%
Wed: executed 137/240 (57%), pass rate 88.3%
Thu: executed 185/240 (77%), pass rate 89.7%
Days needed for the remaining 55 tests: 2

The pass rate is rising as fixes arrive, and at the current pace the remaining tests need two more days. If the release is tomorrow, the lead must raise this today, not on release morning.

At the end, a test summary report states what was tested, what was not, the final metrics, open risks and a recommendation, so stakeholders can make an informed release decision.

Common mistakes

  • A plan nobody reads. Keep it short, link it from the team's board and update it when scope changes.
  • No "out of scope" section. Unstated exclusions become surprises after release.
  • Equal effort everywhere. Spending as long on the profile photo as on payments is a planning failure.
  • Reporting only pass counts. Also report what was not tested and the risks that remain.

Key points

  • A test strategy is the long-term approach; a test plan is the concrete plan for one release.
  • A plan covers objectives, scope in and out, approach, environment, entry and exit criteria, schedule, team, risks and deliverables.
  • Risk-based testing scores likelihood times impact and tests the highest risks first and deepest.
  • The three-point estimate (O + 4M + P) / 6 gives a balanced effort estimate.
  • Monitor progress, pass rate, defects and blocked tests daily, and end with a test summary report.

Exercise

A college admission portal in Lucknow will open in two weeks. List five product risks for it, give each a likelihood and impact from 1 to 5, and change the risk program to print them in order with a suggested test depth. Then write two exit criteria for this release.

Show solution
Python
risks = [
    ("Fee payment charged but form not submitted", 3, 5),
    ("Merit list rank calculated wrongly", 2, 5),
    ("Site slows down on the last date", 4, 4),
    ("Document upload rejects valid PDFs", 3, 3),
    ("Confirmation email has wrong course name", 2, 2),
]

for name, likelihood, impact in sorted(risks, key=lambda r: r[1] * r[2], reverse=True):
    score = likelihood * impact
    depth = "Thorough" if score >= 12 else "Standard" if score >= 6 else "Light"
    print(f"{score:>2}  {depth:<9} {name}")
Output
16  Thorough  Site slows down on the last date
15  Thorough  Fee payment charged but form not submitted
10  Standard  Merit list rank calculated wrongly
 9  Standard  Document upload rejects valid PDFs
 4  Light     Confirmation email has wrong course name

Example exit criteria: "All Thorough-risk test cases have passed" and "the portal handles the expected last-day load in a performance test with no Critical bugs open". Note that the merit-list risk has a top impact score; many teams would test it thoroughly anyway, because its impact on students is so high.

Quick Quiz

1. Which document usually covers many projects and changes rarely?

2. In risk-based testing, what two ratings make up the risk score?

3. Using the three-point estimate, what is the estimate for O = 2, M = 4, P = 12 days?

4. Why should a test plan have an "out of scope" section?

Learn Software Testing with a mentor

Free lessons get you started. Our Software Testing training adds real projects and code reviews from working developers.

  • Project-based learning
  • Mentor code reviews
  • Free counselling call