
A scripted test can only find a bug you already thought of. You pictured a way the feature could break, wrote a check for it, and that check guards that one case from then on. That is worth having. It is also a ceiling. A suite that comes back all green is telling you the failures you predicted did not happen. The bugs you never pictured stay invisible to it.
None of that is a dramatic claim. It is normal product work. The login test passed, but the user got trapped after resetting the password. The checkout test passed, but the total was stale after the cart changed. The mobile flow looked fine in the happy path, but on a real device the button felt frozen long enough for a user to tap twice.
Exploratory testing is how you find those. It is skilled investigation: you use the product, follow what you notice, and keep asking the questions a script was never told to ask. Not random clicking. A session with a mission, notes, and evidence at the end.
What does this actually prove? Where can this break? What happens with real data?
I care about it because it catches the messy bugs that never fit neatly into a pre-written test case. It is also where QA earns a place early in the conversation, because a good session turns a vague worry into evidence the team can act on.
What I mean by exploratory testing
The formal definition I still like is the simple one from Satisfice: learning, test design, and test execution happen at the same time.
That last part is what people skip. You are not throwing structure away. You are designing the next test from what the last one just taught you.
If the payment button stays disabled for four seconds, I do not keep marching through the original checklist. I ask why it feels frozen. I try a slower network. I tap once, then wait. I tap twice. I background the app during the payment call. I check whether the order was created once or twice.
The session changes because the product taught me something.
That is different from ad-hoc testing. Ad-hoc testing has no memory. Exploratory testing has a mission, notes, evidence, and a clear story at the end:
- what I tested
- what I found
- what I did not reach
- what still worries me
- what needs to become a scripted check, bug report, or product question
If I cannot explain that after the session, I was just clicking.
Start with a charter, not a giant script
Before I explore, I do not write a giant script. I write a charter. A charter is the mission for the session. It keeps the work focused without deciding every step in advance.
For a sample food-delivery app I will call Vendly (a made-up app I use for examples), I might write one sentence: explore Vendly guest checkout, with a slow mobile connection, one cart item, one expired card, and one declined card, to discover whether payment failures are clear, recoverable, and safe from duplicate orders.
That is enough structure to begin. It tells me the target, the risk, and the kind of evidence I need. From there a session has a shape: the charter points you, you explore and the product feeds back into what you try next, and you close with notes and a debrief.
I also write down the setup before I touch the product:
| Setup item | Value |
|---|---|
| Build | Web preview build 482 |
| Device | Pixel 7a, Chrome mobile viewport |
| Network | Slow 3G throttle |
| Account state | Guest user |
| Test data | Ackee Bowl in cart, expired card, declined card |
| Main risk | A user cannot recover from payment failure or gets charged twice |
This looks small, but it saves you later. When a developer asks what build, what device, or what data you used, you should not have to reconstruct it from memory.
The screen I would actually test
Here is the kind of screen I want in front of me for the session. Not a perfect design mock. A realistic enough product surface with totals, state, actions, error messages, and places where timing or data can go wrong.
What I am watching
- Does the user know the card failed?
- Can they retry without losing the cart?
- Does the Pay button look frozen?
- Was an order created in the backend?
- Could a double tap create two orders?
The reason I like a real-looking screen is that it forces better questions. A paragraph about “payment failure handling” is easy to nod at. A screen makes you notice the specific claims it puts in front of the user:
- The cart is still saved.
- The button can be pressed again.
- The total is $18.25.
- The payment failed, so no order should exist yet.
- The message is clear enough for a real user to recover.
Each of those is a claim I can go check. A block of prose about error handling gives me nothing to point at.
How to run a session-based exploratory test
I would time-box this to 60 or 90 minutes. I want enough time to follow a lead, but not so much time that the session becomes a wandering afternoon.
The first pass is simple:
- Add an item to the cart.
- Continue as a guest.
- Enter delivery details.
- Try the expired card.
- Try the declined card.
- Retry with a valid card.
- Check the confirmation screen, email, order history, or API response if I have access.
Then I start varying the things that can expose risk:
| Variation | Why I would try it |
|---|---|
| Slow network | Payment flows often feel broken before they technically fail. |
| Double tap Pay | This is where duplicate orders and duplicate charges can show up. |
| Background the app mid-payment | Mobile users do this constantly. The product still has to recover. |
| Edit the cart after a failed payment | Totals and payment state can desync. |
| Expired session | Checkout is high risk when authentication or guest state expires mid-flow. |
| Sold-out item during checkout | The UI may still show the item even when the system cannot fulfill it. |
This is where the session earns its keep. The goal is plain: keep asking what would make you uncomfortable shipping this.
Session notes that are readable
The short example should not look like code because it is not code. It is a working record of the session. I want it readable by a developer, product manager, or another tester who needs to understand what happened.
That log gives the team something to use. It shows the action, the observation, the decision, and the evidence trail.
This is not hypothetical for me. On a large retail platform I tested, an exploratory pass on the basket is where I caught a stale-total problem that the scripted checks were happy with. The flow was a promotion that grew with cart subtotal, the kind that says “spend a bit more and save more.” I added an eligible item to push the cart over a threshold, and the discount tier updated, but the “spend X more to reach the next tier” number did not move with it. The total on the screen was now wrong against the cart that had actually changed. The happy-path tests passed because a discount applied. What no script had asked was whether the next-tier number stayed correct at the exact boundary where the cart crossed it. I would never have gone looking for that on the script. I found it because I kept poking at the cart after it changed, which is exactly what a session is for.
If I found the high-risk order mismatch, I would not leave it buried in the session notes. I would turn it into a bug report with:
- title: Vendly creates an order after a failed guest checkout payment
- build and environment: build 482, Pixel 7a, slow 3G
- steps to reproduce
- expected result: failed payment creates no order
- actual result: UI says payment failed, backend shows order ID
- evidence: screenshot, network request, order ID, timestamp
- impact: guest users may believe payment failed while an order exists
This is where the bug report template helps. Exploratory testing can find the issue, but the report has to make it fixable.
What to capture in a session sheet
I keep the session sheet light. If the template is too heavy, people stop using it. But it must capture enough to make the work trustworthy:
- The charter and risk I am chasing.
- The setup: build, environment, device, browser, data, account state.
- Coverage: the areas I reached and the areas I did not.
- Timestamped actions and observations as the session runs.
- Bugs filed, with their ticket IDs.
- Questions that blocked certainty, product or technical.
- Follow-up: what should be automated, retested, or explored next.
The fillable version of exactly this sheet is at the end of the article.
My personal rule is simple: the notes should be good enough that another tester could continue the investigation tomorrow.
They do not need to be pretty. They need to be honest.
Where to point your curiosity
If you stare at a feature and think “where do I even start”, use lenses. A lens is just a way to stop yourself from testing only the obvious path.
For checkout, I would use these:
| Lens | Question | Vendly example |
|---|---|---|
| Data | What values can change under me? | Quantity, tax, delivery fee, sold-out item, promo code. |
| Time | What happens before, during, and after the action? | Double tap Pay, timeout, delayed confirmation email. |
| State | What state is the user or system in? | Guest user, expired session, cart already changed. |
| Interface | What systems does this depend on? | Payment provider, email service, order service. |
| Platform | Where could the experience differ? | Real Android device, mobile browser, slow network. |
| Recovery | Can the user get out safely? | Retry payment, edit card, return to cart, cancel order. |
I especially like data, time, and recovery. Those are where I find the bugs that hurt. A happy-path automated test proves the flow works once, under perfect conditions, and a real user is never under perfect conditions. Human curiosity is still one of the strongest testing tools we have, and this is where it pays off.
What should become automation
Exploratory testing and automation work together. A session often tells you what automation is worth writing.
After this session, I would not automate every note. I would choose the checks that give repeatable release confidence:
| Finding | Automate it? | Why |
|---|---|---|
| Expired card shows a clear error and keeps cart saved | Yes | Stable, important recovery behavior. |
| Failed payment must not create an order | Yes, if the test can verify the order state through API or test tooling | This protects money and trust. |
| Button felt frozen for 4 seconds | Maybe not as a functional test | Better as a UX issue, performance budget, or visual review. |
| Total stayed stale after cart edit | Yes | Data accuracy bug that can return. |
| ”This message feels confusing” | No | Keep it as human review unless the copy is explicitly required. |
Not every test deserves to be automated. Automate what gives the team repeatable confidence, not what looks impressive in a dashboard.
Where AI helps and where it does not
AI can help with exploratory testing, but I would not hand it the judgment.
I would use an agent to:
- summarize a PRD into risk areas
- draft starting charters
- generate test data combinations
- inspect network calls or logs while I explore
- turn my notes into a clean bug report
- suggest follow-up automation candidates
I would not expect it to fully replace the session. The human part is noticing that the screen feels frozen, the recovery path is confusing, the error message does not match what happened, or the flow would make a real user lose trust.
That is the same line I draw in AI-assisted QA more broadly. Let the tool do the mechanical work. Keep the risk sense, visual judgment, and release decision with the human. If you want the broader argument, I wrote about that in QA Is the Control Layer for AI-Assisted Development.
A practical session template
This is the session sheet I keep. Copy it into your wiki, your tracker, or a plain text file and reuse it every session, one filled-in copy per charter. Keeping the sheet identical run to run is what makes a stack of sessions comparable later, instead of a pile of notes in different shapes.
| Field | Fill it in |
|---|---|
| Charter | Explore ___ with ___ to discover ___. |
| Build and environment | Build, branch, device, browser, network, account state. |
| Main risk | What would make this unsafe or embarrassing to ship? |
| Data | What records, cards, users, permissions, or edge values did you use? |
| Notes | Timestamp, action, observation, decision. |
| Bugs filed | Ticket ID, title, severity, evidence. |
| Questions | Anything unclear that blocks confidence. |
| Follow-up | Retest, automate, ask product, improve test setup. |
At the end, do a ten-minute debrief. You can do it with a teammate or by yourself before you close the session. Answer these plainly:
- What did I learn?
- What did I prove?
- What still worries me?
- What evidence would make us comfortable shipping?
- What should become a repeatable check?
A good session ends with the team holding better evidence than it started with. Charters keep it focused, notes make it trustworthy, and curiosity is what finds the bug no script was told to look for. Pick one risky feature, write a one-sentence charter, time-box an hour, and keep notes as you go. That is enough to start.





Comments 0
Share your thoughts, ask questions, or add to the conversation.