1. Home
  2. Blog
  3. Software Testing

Software Testing

Exploratory Testing: What It Is, How to Do It and a Worked Example

Exploratory testing is not random clicking. Learn how to give it structure with charters, timed sessions and heuristics, follow a complete example and report your findings so the team trusts them.

9 min read
Exploratory testing guide: what it is, how to do it and a worked example

Key takeaways

  • Exploratory testing means learning about a product, designing tests and running them all at once.
  • It is structured: a charter sets the goal, a timebox sets the limit and notes capture the evidence.
  • It finds problems nobody thought to write a test for, which scripted checks and automation can miss.
  • It complements automation and scripted testing. It does not replace them.

Every tester has seen it happen: all the test cases pass, the release goes out, and a customer finds a serious bug within an hour by doing something nobody anticipated. Scripted tests can only check what someone thought of in advance. Exploratory testing is how you go looking for everything else.

This guide shows you how to do it with enough discipline that you can explain what you covered, what you found and what you did not get to. You will need no special tools, only a product to test, a timer and somewhere to keep notes.

What is exploratory testing?

Exploratory testing is an approach where you learn about the software, design tests and execute them at the same time. Each result shapes your next test. If a search box handles an apostrophe strangely, you do not move to the next scripted step. You follow that clue and try quotes, accents and very long input.

Cem Kaner is widely credited with coining the term in the 1980s, and James Bach and others later developed it into a practical discipline. The key idea is that the tester is an investigator using judgement, rather than someone following steps written earlier. A good session answers a question such as “what could go wrong when two people edit this invoice?”

Exploratory vs scripted testing

Aspect Scripted testing Exploratory testing
Test design Before execution During execution
Main goal Confirm known behaviour Discover unknown problems
Guidance Step-by-step test cases A charter and the tester’s skill
Repeatability High Lower, though notes help
Can be automated? Often The thinking cannot be
Best for Regression and compliance New features and risky areas

You need both. Scripted checks protect what already works, and our guide on how to write test cases covers that side. Exploration finds what those checks never considered. Good bugs found while exploring often become new scripted or automated checks, so the two approaches feed each other.

Exploratory vs ad hoc testing

People often use these terms as if they were the same, which is why exploratory testing sometimes gets dismissed. Ad hoc testing usually has no defined goal or record. You try things and hope. Exploratory testing has a mission, a time limit, notes and a debrief. Someone can ask what you covered, and you can answer with evidence.

When to use it

Exploratory testing pays off the most in these situations:

  • A new feature has just arrived. It is the fastest way to learn how it behaves and where the risks are, before you write detailed tests.
  • Requirements are thin or still changing. You can test against your understanding and raise questions early.
  • Time is short before a release. A few focused sessions on the riskiest areas can tell you a lot.
  • An area keeps producing bugs. Defects tend to cluster, so investigate around a recent fix.
  • Usability matters. A human notices when a flow is confusing, even if it technically works.

It is a poor fit where every step must be documented for an audit or where the same large set of checks has to be repeated exactly, as in a full regression run. In those cases, use scripted tests. Your test strategy should say how much of each approach the project needs.

Write a charter

A charter is a short mission statement for one session. It keeps you focused without telling you which steps to take. A popular template comes from Elisabeth Hendrickson’s book Explore It!:

Explore   <target>
With      <resources, tools or data>
To discover <information>

Some charters we might write for an online shop:

  • Explore the checkout with expired, invalid and stacked coupons to discover how totals and error messages behave.
  • Explore the product search with special characters and very long input to discover how well it handles bad data.
  • Explore the account page with two browsers logged in at once to discover what happens with conflicting edits.

A charter that is too broad, such as “test the website”, gives no focus. One that is too narrow, such as “check the coupon field rejects ABC”, is really just a single test case. Aim for something you can reasonably cover in about an hour.

Run timed sessions

Session-based test management, developed by Jonathan and James Bach, turns exploration into something you can plan and report on. It has a simple rhythm:

  1. Pick one charter. Choose it based on risk.
  2. Set a timer. 45 to 90 minutes works well, and you should avoid interruptions.
  3. Test and take notes. Record what you tried, what you saw, any bugs and any questions.
  4. Stay on mission. If you spot something unrelated, write it down as a new charter and return to the current one, unless it is more important.
  5. Debrief. Spend ten minutes with a colleague going through what you covered, what you found and what still worries you.

Tip: Keep a screen recording running during sessions. When a strange bug appears, you may not remember the exact steps, and the recording saves you from having to reproduce it from memory.

Useful heuristics

A heuristic is a rule of thumb that gives you ideas when you are stuck. These are good ones to start with:

Heuristic What to try
Zero, one, many No items, a single item and a very large number of items
Too big, too small, just right Sizes and lengths around the expected range
Interrupt it Refresh, press back, lose the network or log out midway
Do it twice Double-click Pay, or submit the same form in two tabs
CRUD Create, read, update and delete every kind of object
Follow the data Check that a value entered here appears correctly everywhere else
Change the user Try the same action with a different role or permission

For a broader checklist, look up James Bach’s SFDPOT mnemonic: Structure, Function, Data, Platform, Operations and Time. When you are testing limits, boundary value analysis tells you precisely which values matter most.

A worked example

Here is how a 60-minute session on a coupon feature could go. This is an illustration of the process, not a report from a real product.

Charter:  Explore checkout coupons with expired, stacked and
          oddly formatted codes to discover pricing errors.
Duration: 60 minutes
Tester:   Priya
Build:    2.14.0 on staging, Chrome

Notes
10:02  SAVE10 on a 500 cart gives 450. Correct.
10:08  " save10 " with spaces is accepted. Reasonable.
10:15  Expired code shows "Invalid code". Unclear wording.  QUESTION
10:21  SAVE10 then WELCOME5: second replaces first, no warning.  QUESTION
10:30  Apply SAVE10, then remove item to empty cart. Total is -50.  BUG
10:38  Same bug with one item left at a low price: total goes negative.
10:47  Apply code in two tabs, pay in one. Code used twice.  BUG
10:58  Not covered: gift cards, currency other than INR.  NEW CHARTER

Notice how the session flowed. The negative total was not on anyone’s list. It came from wondering what happens when the cart changes after a coupon is applied, and that discovery led straight to the next test. The session ended with two bugs, two questions for the product owner and a new charter, which is a very useful hour.

Report your findings

Exploration is only valuable if other people can act on the result. At the end of a session, share a short summary of:

  • Coverage: what you tested and on which build and environment.
  • Bugs: filed separately, with clear steps. See how to write a bug report.
  • Questions: anything where the right behaviour is unclear.
  • Gaps and risks: what you did not reach, and how worried you are about it.

Then ask which findings should become permanent checks. That double-submission bug, for example, deserves a regression test once it is fixed, and our end-to-end testing best practices can help you automate it well.

Common mistakes

  • Taking no notes. Without them, you cannot reproduce bugs or show what you covered.
  • Having no charter. You drift towards the easy, familiar parts of the product.
  • Measuring only bug counts. A session that finds nothing in a risky area is still useful information.
  • Leaving it to the last day. Serious findings need time to be fixed, so explore early as well as late.
  • Treating it as a job for juniors. Exploration rewards experience and product knowledge. Developers, designers and support staff also make excellent session partners.

Final thoughts

Exploratory testing takes curiosity and turns it into a repeatable practice. Try it this week: choose the riskiest feature in your current sprint, write one charter, set a timer for 60 minutes and keep notes. Debrief with a colleague afterwards. One session is usually enough to show your team why this belongs in the process.

Frequently asked questions

What is exploratory testing in simple words?

It is testing where you learn the product, decide what to try and run those tests all at once, using each result to choose your next step.

Is exploratory testing the same as ad hoc testing?

No. Ad hoc testing is informal and usually undocumented. Exploratory testing has a defined mission, a time limit, written notes and a debrief.

Can exploratory testing be automated?

The thinking cannot, because it depends on human judgement. Tools can still help by generating data, setting up environments, or recording sessions.

How long should an exploratory testing session be?

Between 45 and 90 minutes is common. That is long enough to get deep into an area, but short enough to keep your focus sharp.

Do Agile teams use exploratory testing?

Yes. It suits short sprints well because it needs little preparation, gives fast feedback on new features and can involve the whole team.

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 →