1. Home
  2. Blog
  3. Software Testing

Software Testing

Risk-Based Testing Explained: Score Risks, Build a Matrix and Test What Matters

There is never time to test everything equally. Risk-based testing is a simple, structured way to decide where testing effort goes first, based on how likely something is to fail and how much it would hurt if it did.

10 min read
Risk-based testing explained: score risks, build a matrix and test what matters

Key takeaways

  • Risk-based testing prioritises testing by risk, usually likelihood × impact.
  • A simple 1-to-5 score for each gives a risk value from 1 to 25 that is easy to discuss and sort.
  • High-risk areas get deeper, earlier and repeated testing; low-risk areas get lighter checks.
  • It is a team exercise, repeated every release, not a spreadsheet filled in once.

A release is due Friday. The team has three days and three hundred possible test cases. Testing everything equally means testing the payment flow with the same care as the colour of a settings icon. Risk-based testing replaces that with a deliberate choice: test first and hardest where failure is both likely and costly.

This is a process guide, so it contains no code that we ran. The scores in the worked example are illustrative, chosen to show the method, not measured from a real product.

What is risk-based testing?

Risk-based testing is an approach where the amount and order of testing are driven by product risk. A risk is something that could go wrong, such as a feature failing, data being corrupted or a page being too slow. Each risk is assessed on two dimensions: how likely it is to happen, and how severe the impact would be. The combination decides how much testing it deserves.

It is not a separate test type, like performance or security testing. It is a way of planning and prioritising all of them, and it fits naturally into a test strategy.

Why it works

  • Time is always limited. Prioritising by risk makes sure the most important checks happen even if time runs out.
  • Bugs are not evenly spread. Complex, new and frequently changed code tends to hold more defects.
  • Impact is not equal. A wrong total at checkout and a misaligned footer are both bugs; only one loses money.
  • It makes trade-offs visible. Stakeholders can see what was tested deeply and what was accepted as lower risk.

The five steps

  1. Identify risks with the team.
  2. Score each one for likelihood and impact.
  3. Prioritise using a risk matrix.
  4. Plan and test with depth matched to risk.
  5. Review after testing and after release, and update the scores.

Step 1: identifying risks

Gather testers, developers and someone who understands the business, such as the product owner. Walk through features, user journeys and recent changes, and ask what could go wrong. Useful prompts:

  • Where would a failure cost money, break the law, or lose data?
  • What changed in this release, and what does it touch?
  • Which areas have had many bugs or incidents before?
  • What depends on third parties, such as payment gateways or APIs?
  • What is new technology or unfamiliar code for the team?
  • What happens under load, on slow networks or on older devices?

Write each risk as a short, specific statement, such as “Order total is wrong when a coupon and free shipping apply together”, not just “Checkout”.

Step 2: scoring likelihood and impact

A 1-to-5 scale is common because it is quick to agree on:

Score Likelihood Impact
1 Very unlikely Cosmetic, easy workaround
2 Unlikely Minor inconvenience
3 Possible Feature partly broken for some users
4 Likely Key feature broken, revenue or reputation affected
5 Very likely Data loss, security breach, legal or financial damage

Risk score = likelihood × impact, giving 1 to 25. Likelihood rises with complexity, amount of change, past defects and developer unfamiliarity. Impact rises with the number of users affected, money involved, safety, data and legal exposure. Agree definitions in advance so that a “4” means the same thing to everyone.

Step 3: the risk matrix

              Impact →
              1    2    3    4    5
Likelihood 5  5   10   15   20   25
           4  4    8   12   16   20
           3  3    6    9   12   15
           2  2    4    6    8   10
           1  1    2    3    4    5

Plot each risk on the grid. Scores in the top-right corner are your priorities; scores in the bottom-left can receive light checks. Many teams colour the bands: for example, 15 to 25 high, 8 to 14 medium and 1 to 7 low. These thresholds are a convention, not a standard, so adjust them to your context. Some teams use a simpler 3 × 3 grid of low, medium and high, which is often enough.

Tip: Watch for items with high impact but low likelihood, such as a rare data-loss scenario. Their multiplied score may look modest, but a single occurrence can be catastrophic. Many teams treat any impact of 5 as at least medium priority regardless of likelihood.

Step 4: mapping risk to test depth

Risk level Testing approach
High (15-25) Test early and thoroughly: detailed test cases, negative and boundary tests, exploratory sessions, automation in every build, reviews by a second tester
Medium (8-14) Core scenarios plus key edge cases, included in the regression suite
Low (1-7) Smoke checks or a quick exploratory pass; may be deferred if time runs out

Depth means more than number of test cases. For high risks, consider stronger techniques, such as boundary value analysis and decision tables, independent review of test design, testing on more devices and environments, and monitoring after release.

Step 5 in practice: a worked example

An online shop is releasing a new coupon feature. The team lists and scores risks (illustrative scores):

Risk Likelihood Impact Score Level
Wrong order total with coupon + free shipping 4 5 20 High
Coupon usable more than its limit 3 4 12 Medium
Payment gateway timeout during checkout 2 5 10 Medium (watch: impact 5)
Coupon field accepts invalid characters 3 2 6 Low
Coupon banner misaligned on tablets 3 1 3 Low

The plan follows directly. The total calculation gets detailed tests for every combination of coupon, shipping rule and tax, automated unit tests, and an exploratory session. The usage limit gets concurrency tests, since two simultaneous checkouts are the likely way to exceed it. The gateway timeout gets a few failure-injection tests, because its impact is severe even though the score is medium. The banner gets a glance on one tablet. If time runs out on Thursday, it is the banner that waits, by deliberate choice.

Where risk data comes from

Scores start as informed judgement, but data makes them better:

  • Defect history: modules with many past bugs. Our bug life cycle guide covers tracking these.
  • Code churn: files changed most often in version control.
  • Production incidents and support tickets.
  • Usage analytics: the most used journeys have the most users at risk.
  • Test coverage gaps: areas with little automated coverage; see code coverage explained.

Risk-based testing in agile and CI

In short sprints, a full workshop each time is too heavy. A lighter version works well: discuss risks during refinement, tag stories as high, medium or low risk, and agree the testing depth as part of the definition of done. In CI, run tests for high-risk areas on every commit and broader suites less often. The test pyramid helps decide the level: push high-risk logic into fast unit tests where possible, and keep end-to-end tests for the riskiest user journeys.

Common mistakes

  • Scoring alone. A tester working alone misses business impact and technical complexity. Score as a group.
  • Scoring once. Risks change as code changes. Review the list every release.
  • Treating low risk as “no testing”. Low risk means lighter testing, not none.
  • False precision. Arguing whether something is 12 or 15 wastes time; the ranking matters more than the exact number.
  • Hiding the trade-offs. Report which risks were tested lightly or not at all, so stakeholders can accept them knowingly.

Reporting risk coverage

A test report organised by risk is far more useful to decision-makers than a raw pass count. For each risk, show its level, what testing was done, the result and anything still open:

Risk Level Testing done Status
Wrong total with coupon + free shipping High 32 cases, automated, exploratory session Passed after 1 fix
Coupon usage limit exceeded Medium Concurrency tests 1 open bug, fix in progress
Coupon banner on tablets Low Not tested this release Accepted risk

The example rows are illustrative. The point is the format: anyone can see at a glance that the most dangerous areas were tested thoroughly, which risks remain, and what was consciously left out. “Ready to release?” becomes a discussion about specific risks, not a feeling.

Final thoughts

Risk-based testing is common sense made explicit: spend the most effort where failure is most likely and most costly. List risks with the whole team, score likelihood and impact on a simple scale, plot them on a matrix, and match test depth to the result. Then revisit the scores each release, using real defect and incident data to make the next round sharper.

Frequently asked questions

What is risk-based testing?

A testing approach that prioritises effort according to product risk, usually scored as likelihood multiplied by impact, so the most dangerous areas are tested first and most thoroughly.

How do you calculate a risk score?

Rate likelihood and impact on a scale such as 1 to 5, then multiply them. A score of 20 or 25 is high priority; low scores get lighter testing.

What is a risk matrix in testing?

A grid with likelihood on one axis and impact on the other. Plotting each risk on it shows which areas need the most testing.

Who should take part in risk assessment?

Testers, developers and someone representing the business or users, such as a product owner. Each sees different kinds of risk.

Does low risk mean an area is not tested?

No. Low-risk areas still get basic checks, such as smoke tests. They are simply tested less deeply and later than high-risk areas.

Keep learning

Work with Stack Quora

Need help with testing, WordPress or SEO?

We help teams ship better software and grow their sites. Tell us what you are working on and we will suggest a clear next step.

Keep reading

More guides on testing, AI & modern development

Enjoyed this article? Pick a topic and jump straight into our newest tutorials.

Artificial Intelligence

LLM Structured Output Explained: Getting Reliable JSON From AI Models

LLM structured output explained with validation we ran in Pydantic: JSON mode and schemas, constrained decoding, the ways model output…

Read article →
DevOps

SSH Keys Explained: How They Work, ssh-keygen, Ed25519 and Safe Habits

SSH keys explained with keys we generated: public vs private keys, ssh-keygen, Ed25519 vs RSA, fingerprints, passphrases, ssh-agent, authorized_keys, config…

Read article →
DevOps

HTTP Caching Explained: Cache-Control, ETag and 304 Responses, With a Live Test

HTTP caching explained with a small server we ran: Cache-Control directives, max-age, no-cache vs no-store, ETag revalidation and 304 responses,…

Read article →
Test Automation

API Contract Testing Explained: Catch Breaking Changes Before They Ship

API contract testing explained with a schema check we ran: what a contract is, consumer-driven contracts, Pact, OpenAPI, which changes…

Read article →
Software Testing

Risk-Based Testing Explained: Score Risks, Build a Matrix and Test What Matters

Risk-based testing explained step by step: identifying risks, scoring likelihood and impact, building a risk matrix, mapping risk to test…

Read article →
Databases & SQL

SQL Constraints Explained: NOT NULL, UNIQUE, CHECK and FOREIGN KEY, Tested

SQL constraints explained with tests we ran: NOT NULL, UNIQUE, CHECK, DEFAULT, PRIMARY and FOREIGN KEY, the NULL loopholes, SQLite's…

Read article →
Databases & SQL

SQL Date Functions Explained: Adding, Comparing and Grouping Dates Without Bugs

SQL date functions explained with queries we ran: adding intervals, month-end surprises, date differences, the BETWEEN trap, grouping by day,…

Read article →
Software Development

Python asyncio Explained: async, await, gather and TaskGroup With Real Timings

Python asyncio explained with code we timed: coroutines, await, gather, TaskGroup, error handling, timeouts, limiting concurrency and the blocking-call mistake…

Read article →
Software Development

Debounce vs Throttle in JavaScript: How They Work, When to Use Each, Tested

Debounce vs throttle in JavaScript explained with timings we measured in Node.js: how each works, simple implementations, leading and trailing…

Read article →
Software Development

Python Context Managers Explained: The with Statement, contextlib and Real Uses

Python context managers explained with code we ran: how with works, __enter__ and __exit__, contextlib.contextmanager, suppress, ExitStack, database transactions and…

Read article →
Artificial Intelligence

LLM Temperature and Top-p Explained: How AI Models Choose Their Next Word

LLM temperature and top-p explained with a simulation we ran: how probabilities are reshaped, what top-p keeps, recommended settings by…

Read article →
DevOps

YAML Explained: Syntax, the Norway Problem and Other Traps We Tested

YAML explained with a parser test: basic syntax, lists and maps, the Norway problem, versions turning into floats, octal zip…

Read article →
DevOps

Cron Jobs Explained: Syntax, Real Schedules and the Mistakes That Break Them

Cron jobs explained with schedules we verified: the five fields, operators, real examples, the day-of-month OR day-of-week trap, environment problems,…

Read article →
Software Testing

Bug Life Cycle in Software Testing: Every Status, Who Owns It and Common Mistakes

The bug life cycle explained: every defect status from New to Closed, who owns each step, rejected, deferred and reopened…

Read article →
Test Automation

Property-Based Testing in Python: Hypothesis Finds the Bugs Your Examples Miss

Property-based testing explained with Hypothesis tests we ran: properties vs examples, strategies, shrinking, the real bugs it found in our…

Read article →
Databases & SQL

SQL Pagination Explained: OFFSET vs Keyset, With a Million-Row Test

SQL pagination explained with a million-row test we ran: LIMIT and OFFSET, why deep pages get slow, keyset (cursor) pagination,…

Read article →
Databases & SQL

SQL EXISTS vs IN: Differences, the NOT IN NULL Trap and Performance

SQL EXISTS vs IN explained with queries we ran: how each works, why NOT IN returns no rows when a…

Read article →
Software Development

Python Logging Explained: Levels, Handlers, Formatters and Mistakes to Avoid

Python logging explained with code we ran: levels, basicConfig quirks, named loggers, handlers and formatters, logger.exception, lazy formatting, duplicate logs…

Read article →
Software Development

JavaScript Map vs Object: Key Differences, Pitfalls and a Benchmark

JavaScript Map vs Object explained with code we ran in Node.js: key types, ordering, the prototype trap, JSON, size, WeakMap…

Read article →
Software Development

Python Type Hints Explained: Annotations, mypy and the Errors It Catches

Python type hints explained with a real mypy run: basic annotations, Optional and unions, TypedDict, Literal, Protocol, generics, Callable, strict…

Read article →
Artificial Intelligence

LLM Tokens Explained: How AI Models Read Text, Count Costs and Fill Context Windows

LLM tokens explained with a tokenizer we ran: how text is split, why counts differ by language and tokenizer, context…

Read article →
DevOps

Semantic Versioning Explained: MAJOR.MINOR.PATCH, Ranges and Release Rules

Semantic versioning explained with code we ran: MAJOR.MINOR.PATCH rules, pre-releases, correct version sorting, caret and tilde ranges, 0.x versions, lockfiles…

Read article →
DevOps

Git Reset vs Revert: How to Undo Commits Safely, With a Tested Example

Git reset vs revert explained with a repository we built: soft, mixed and hard reset, revert commits, reverting merges, recovering…

Read article →
Software Testing

The Test Pyramid Explained: Layers, Ratios and When to Break the Shape

The test pyramid explained: unit, integration and end-to-end layers, sensible ratios, the ice cream cone anti-pattern, the testing trophy and…

Read article →
Test Automation

pytest Fixtures Explained: Scope, yield Teardown, conftest.py and Factories

pytest fixtures explained with a suite we ran: how fixtures work, scopes, yield teardown, conftest.py, factory fixtures, parametrized fixtures, built-ins…

Read article →
Databases & SQL

SQL Upsert Explained: INSERT ON CONFLICT, MERGE and the REPLACE Trap

SQL upsert explained with queries we ran: INSERT ON CONFLICT DO UPDATE and DO NOTHING, the excluded row, conditional updates,…

Read article →
Databases & SQL

SQL LIKE Operator Explained: Wildcards, Case Sensitivity and Performance

The SQL LIKE operator explained with queries we ran: % and _ wildcards, escaping, NOT LIKE and NULL, case sensitivity…

Read article →
Artificial Intelligence

AI Hallucinations Explained: Why Language Models Make Things Up and How to Reduce It

AI hallucinations explained: what they are, why language models produce them, common types, how to reduce them with grounding and…

Read article →
Test Automation

Mocking in Python: unittest.mock, patch and the Mistakes That Make Tests Lie

Mocking in Python with unittest.mock, tested: Mock and return_value, side_effect, patching where a name is used, spec and autospec, mocking…

Read article →
Software Testing

Code Coverage Explained: Line vs Branch Coverage and What 100% Really Means

Code coverage explained with a real coverage.py run: line, branch and condition coverage, reading a report, why 100% coverage can…

Read article →
Artificial Intelligence

What Are AI Agents? How They Work, With a Simple Agent Loop You Can Run

What are AI agents? A plain guide to the agent loop, tools, memory and guardrails, with a small Python loop…

Read article →
Test Automation

TDD vs BDD: Key Differences, One Feature Built Both Ways and When to Use Each

TDD vs BDD explained with one discount feature built both ways: red-green-refactor with code we ran, Given-When-Then scenarios, tools, trade-offs…

Read article →
Software Testing

User Acceptance Testing (UAT): Process, Checklist and Real Examples

User acceptance testing explained: who runs it, how it differs from QA, a seven-step process, a UAT test case template,…

Read article →
Artificial Intelligence

What Are Embeddings? Vectors and Cosine Similarity Explained Simply

What are embeddings? A plain-language guide to vectors, cosine similarity and semantic search, with a small example we ran, common…

Read article →
Test Automation

Flaky Tests: What Causes Them and How to Fix Them for Good

Flaky tests explained with demos we ran: the main causes, how to confirm and diagnose one, proper fixes for timing,…

Read article →
Software Testing

Load Testing vs Stress Testing: Differences, Metrics and k6 Examples

Load testing vs stress testing explained: what each proves, spike and soak tests, the metrics that matter, why averages mislead,…

Read article →