Types of testing
Recognize the main kinds of testing and when each is used.
Topic 4 — Types of testing
Goal: Recognize the main kinds of testing and when each is used.
Lesson 4.1 — Functional testing: does it do what the spec says?
Three weeks into her first QA job at FreshCart, Nadia opens the requirements Tom wrote and reads one line aloud: "Tapping 'Add to Cart' places the selected item in the cart." Then she opens the app, taps Add to Cart on a bag of oranges, and checks the cart. Oranges are there. She writes "Pass" and moves to the next line.
That small loop — read what it should do, do it, compare — is the whole job in miniature. It's called functional testing: checking that a feature does what it's supposed to do, by comparing the actual behavior against the expected behavior written in the requirements.
The word that does the work there is compare. Nadia isn't deciding whether Add to Cart is a good feature, or whether the button is pretty. She has a source of truth — the spec — and she's holding the live app up against it. Match means pass. Mismatch means she's found a bug.
In her pharmacy years, Nadia checked each filled prescription against the doctor's order: right drug, right dose, right patient. Same instinct, new object. The order is the spec; the pill bottle is the build.
Functional testing always needs two things: the behavior you observe, and the behavior you were promised. A bug is the gap between them.
Most of what manual QA does day to day is functional testing. Promo code applies the right discount? Functional. Payment goes through and the order appears in tracking? Functional. Every checkbox in this topic still sits on top of this one idea.
Lesson 4.2 — Smoke and sanity: two fast checks with different jobs
Friday afternoon, Priya pushes a fresh build. Nadia's first instinct is to dive into the promo-code edge cases she's been itching to test. Marcus stops her.
"Before you go deep — does the app even open? Can you log in? Can you get through checkout?"
That five-minute pass has a name: smoke testing. It's a quick, shallow check that the most critical features work at all, run first on every new build. App launches, login works, you can add an item and reach checkout. If smoke testing fails — the app won't even open — there's no point testing the promo-code logic underneath. The build is dead on arrival; send it back.
The name is often traced to hardware or plumbing — power something on, or pump smoke into a pipe system, and if smoke literally pours out, you stop before going any deeper. Nobody's fully settled which trade it came from, but the picture sticks: a fast first look that tells you whether it's even safe to continue.
A clean smoke test doesn't mean the build is good. It means the build is worth testing.
Now contrast a different Friday. Priya didn't ship a whole new build; she fixed one bug — the promo code "FRESH10" was applying a 1% discount instead of 10%. Nadia doesn't need to re-run the entire app. She needs to confirm that one fix actually works. She enters FRESH10, sees 10% come off, tries a couple of nearby cases, and stops.
That narrow, focused check of a single fix or small change is sanity testing. Where smoke is wide and shallow across the whole build, sanity is narrow and a little deeper on the one thing that changed. Smoke asks "is this build alive?" Sanity asks "did this specific fix land?"
People mix these two up constantly, so here's the clean split:
| Smoke | Sanity | |
|---|---|---|
| Scope | the whole build, critical paths | one specific fix or change |
| Depth | shallow, broad | narrow, focused |
| Runs when | every new build, first thing | after a targeted change |
| Answers | "Is it stable enough to test?" | "Did this fix work?" |
Lesson 4.3 — Regression testing: did the new thing break an old thing?
Priya's promo-code fix worked. Nadia confirmed it. She's about to close the ticket when Marcus asks the question that defines her week:
"And checkout — did the fix break checkout?"
Nadia blinks. The fix was about discounts. Why would it touch checkout? But she tests it anyway, and the total now miscalculates tax on discounted orders. The fix that solved one thing quietly broke a neighbor.
Re-testing existing features to confirm a new change didn't break them is regression testing. The feature "regresses" — slips backward — when something that used to work stops working. And it happens constantly, because code is connected: the discount logic and the tax logic share the same total.
This is the type Nadia will spend the most real-world time on, and it's the one most worth understanding. Every fix, every new feature, every dependency update is a chance to break something that was fine yesterday. So before every release the team re-runs a big checklist of "things that already worked" to make sure they still work.
Which raises an obvious problem. That checklist only grows — every release adds more must-still-work cases — and running it all by hand, every time, is brutal. That's exactly why regression testing is the prime candidate for automation. Dev maintains a Playwright suite that re-runs the core flows automatically on every build, so the machine handles the repetitive "still works?" pass and Nadia's human attention goes to the new and the weird. We'll go deep on automation later; for now, just hold the link: regression is repetitive, and repetitive is what we automate.
Lesson 4.4 — Non-functional testing: not what it does, but how well
Everything so far asked the same question — does the feature work? But Nadia's checkout could pass every functional test and still be a bad experience. Picture it: Add to Cart works, payment works, tracking works… and the page takes nine seconds to load, or the layout is so cramped on a phone that nobody can find the Pay button.
That's a different axis entirely. Non-functional testing checks how well the product works, not what it does. The main members of the family:
- Performance — is it fast enough, and does it survive load? FreshCart at 6 p.m. dinner rush has thousands of people checking out at once; performance testing asks whether it stays quick or buckles.
- Usability — is it easy and pleasant? Can a first-time user find the promo field without a treasure hunt?
- Security — can it be broken into or misused? Can someone tamper with the price, reuse a one-time promo, or reach another user's order?
- Compatibility — does it work across the browsers, devices, and screen sizes the team supports?
That last one bites teams more than beginners expect. Nadia hits it firsthand: the Pay button works perfectly in Chrome and does nothing in Safari. Same code, different browser, real bug — and it would ship straight to customers if QA only tested in one place. Screen size is the same story: a layout that's clean on a laptop can shove the checkout button off the bottom of a small phone. So QA deliberately tests across the browsers and devices the team supports.
Manual QA usually owns functional, usability, and compatibility testing. Performance and security often lean on specialists and dedicated tools — but you're expected to know they exist and to flag a "this feels slow" or "could someone abuse this?" when you see it.
Lesson 4.5 — Two lenses: black/white box, and positive/negative
Two last distinctions, and they're about how you look at the thing rather than which feature you're poking.
The first is your vantage point. Black box testing means testing without seeing the code — you judge only inputs and outputs, exactly like a real user would. Nadia doesn't read Priya's source; she enters a promo code and watches what the total does. That's black box, and it's the heart of manual QA. White box testing means testing with knowledge of the internal code — you can see the branches and conditions inside, so you target them deliberately. That's mostly developer and automation territory; Priya's unit tests are white box.
The second lens is what you feed it. Positive testing uses valid input and checks the feature works: type a real email, nadia@freshcart.com, and it's accepted. Negative testing uses invalid input and checks the feature fails gracefully: type banana in the email field and you should get a clear "please enter a valid email," not a frozen screen or a crash.
Beginners test the happy path and stop — valid email, valid card, item in stock, done. But the ugly, embarrassing, customer-losing bugs almost always hide in the nasty inputs: the empty field, the expired card, the promo code typed in capitals, the quantity of -1. Strong testers love negative testing for exactly that reason.
Anyone can confirm the right input works. The tester's edge is asking, "what happens when someone does the wrong thing?"
So Nadia's reflex, on every field she meets, is to try it twice: once the way it's meant to be used, and once the way a tired, fat-fingered, slightly mischievous human actually uses it.
Worked example — One promo-code fix, six types of testing
Priya ships a fix: promo code "FRESH10" now correctly applies 10% off. Watch how many testing types Nadia walks through before she'll call it done.
It's a fresh build, so she starts with smoke testing — app opens, login works, she can reach checkout. Alive. Worth testing.
Now the change itself: a focused sanity check. She enters FRESH10, confirms 10% comes off the right subtotal. The fix landed.
That's the new behavior. But Marcus's question rings in her ears, so she runs regression testing on the neighbors — full checkout, tax calculation, the order showing up in live tracking — to make sure the discount fix didn't dent anything that already worked. (Dev's Playwright suite re-runs the core flows too, automating the boring part of this.)
Every check so far has been functional — comparing behavior to Tom's spec — and black box: Nadia never opened Priya's code, she just used the app like a customer.
Then she pushes on the input itself. Positive: valid code, real cart, discount applies. Negative: an expired code (clear error?), a fake code "BANANA10" (graceful rejection?), FRESH10 applied twice (does the one-time limit hold?). The double-apply case turns out to be a real bug — and it lives squarely in negative-testing territory, which is exactly why she looked.
Last, a quick non-functional pass: she opens checkout in Safari as well as Chrome (compatibility) and notices the discounted total renders a beat slowly on her phone (performance), which she notes for the specialists.
One small fix. Six types of testing. That ability — to look at any change and know which kinds of testing it calls for — is the entire point of this topic.
Key terms
- Functional testing — checking a feature does what it should, by comparing actual behavior to the expected behavior in the requirements.
- Smoke testing — a quick, shallow check that the most critical features work at all, run first on every new build.
- Sanity testing — a narrow, focused check that one specific fix or small change works; narrower than full regression.
- Regression testing — re-testing existing features to confirm a new change didn't break them; the prime candidate for automation.
- Non-functional testing — checking how well the product works (performance, usability, security, compatibility) rather than what it does.
- Compatibility testing — confirming the product works across the supported browsers, devices, and screen sizes.
- Black box / white box — testing without seeing the code (like a user) vs. testing with knowledge of the internal code.
- Positive / negative testing — checking valid input works vs. checking invalid input fails gracefully.
Try this
Pick any app on your phone with a sign-up or login screen. Run two passes on the email field. First, positive: enter a valid address and confirm it's accepted. Then negative: enter banana, then leave it blank, then enter a@b with nothing after the dot — and watch how it responds. Did each get a clear, polite error, or did anything freeze, crash, or accept junk? Write down what you tried and what happened. You just did black-box, functional, positive and negative testing on a real product — the same moves Nadia makes on her first morning.
Common pitfalls
- Only testing the happy path. Valid email, valid card, item in stock — and stopping there. The worst bugs hide in the invalid inputs, which is why negative testing matters so much.
- Confusing smoke with sanity. Smoke is wide and shallow across a whole new build ("is it alive?"); sanity is narrow and focused on one specific fix ("did this work?"). Different jobs.
- Skipping regression. Confirming the fix works but never checking whether it broke a neighbor. Fixing one thing routinely breaks another — that's the whole reason regression exists.
- Forgetting non-functional. A feature can pass every functional test and still be too slow, broken in Safari, or unusable on a small screen. "It works" isn't the same as "it works well."
Key takeaways
- Functional testing compares a feature's actual behavior to the expected behavior in the requirements; it's most of manual QA's day.
- Smoke (whole build, shallow, runs first) and sanity (one fix, focused) are two fast checks with different jobs — don't confuse them.
- Regression testing re-tests existing features after a change and is the prime candidate for automation, because it repeats every release.
- Non-functional testing checks how well it works — performance, usability, security, compatibility (a Chrome-vs-Safari break is the classic compatibility bug).
- Black box (like a user, no code) is manual QA's home; negative testing (invalid input, graceful failure) is where the nastiest bugs hide.
Preparing your quiz…