Open this lesson in your favourite AI. It'll walk you through the why, explain the demo, and quiz you on the try-it list.
Saying 'we did testing' is like saying 'we ate food' — technically true, completely uninformative. A QA engineer needs a working vocabulary of testing types to design a test strategy, communicate coverage to stakeholders, and identify gaps. The taxonomy splits along several axes: by scope (unit → integration → system → acceptance), by objective (functional vs non-functional), by execution method (manual vs automated), and by timing (smoke before regression, regression before exploratory). Knowing which type is needed when — and which you're missing — is the core skill of test planning.
Testing type vocabulary lets QA engineers communicate coverage gaps precisely instead of vaguely. Saying 'we're missing regression coverage for the checkout module' is actionable; 'we haven't tested enough' is not. Each type in this taxonomy targets a distinct failure mode — unit tests catch logic errors, smoke tests catch deploy failures, security tests catch vulnerability classes that functional tests never reach.
taxonomy to only automated tests: [t for t in taxonomy if t.automated]. What percentage of the total is automated? For the remaining manual ones, write a one-line explanation of why they're hard to automate.cost: str field with values 'low', 'medium', 'high'. Assign costs (unit tests = low, performance = high, security = high). Sort by cost. This is the data behind the 'test pyramid' — cheap-to-run tests at the bottom, expensive at the top.Use these three in order. Each builds on the one before.
In one paragraph, explain the difference between smoke testing and regression testing. When would you run each, and what happens if the smoke test fails?
Walk me through how you'd design a test strategy for a new payment feature: which test types in which order, what coverage each provides, and what risk is left uncovered by each type.
A PM asks you to cut testing time in half for the upcoming release. Walk me through how you'd decide which test types to prioritize vs skip, how you'd communicate the residual risk, and how you'd measure whether the decision was correct after the fact.
from dataclasses import dataclass
from typing import List
@dataclass
class TestType:
name: str
scope: str # unit | integration | system | acceptance
goal: str
run_by: str # developer | qa | product | automated
when: str
automated: bool
taxonomy = [
TestType("Unit test", "unit", "Verify one function/class in isolation", "developer", "On every commit", True),
TestType("Integration test", "integration", "Verify two+ components work together", "dev/qa", "On every PR", True),
TestType("Smoke test", "system", "Verify critical paths after a new build", "qa/auto", "After every deploy", True),
TestType("Regression test", "system", "Verify nothing broke after a change", "qa/auto", "Before every release", True),
TestType("Exploratory test", "system", "Discover unexpected bugs via unscripted testing", "qa", "When new features land", False),
TestType("UAT", "acceptance", "Verify the system meets business requirements", "product/ux", "Before go-live", False),
TestType("Performance test", "system", "Verify speed, throughput, and stability under load","qa/sre", "Before scaling or major release",True),
TestType("Security test", "system", "Find vulnerabilities before attackers do", "qa/security","Before every release", True),
TestType("Sanity test", "system", "Quick check that a specific fix/feature works", "qa", "After a bug fix is deployed", False),
TestType("A/B test", "acceptance", "Compare two versions with real users", "product", "In production", True),
]
print(f"{'Test Type':<20} {'Scope':<12} {'Automated':<10} When")
print("-" * 80)
for t in taxonomy:
auto = "yes" if t.automated else "manual"
print(f"{t.name:<20} {t.scope:<12} {auto:<10} {t.when}")python3 main.py