The Testing Vocabulary You'll Actually Use
Part 2 of the Software Testing Course: unit, integration, end-to-end, smoke, regression, flaky, fixture — the terms defined clearly, with the distinctions that matter in practice.
Testing has a lot of jargon, and teams routinely use the same word to mean different things — one person's "integration test" is another person's "end-to-end test," and the disagreement surfaces at the worst possible moment, mid-incident. This part pins down the vocabulary the rest of the course relies on, with the distinctions that actually matter in practice.
Test scope: unit, integration, end-to-end
These three describe how much of the system a test exercises — not how important it is, and not where it runs.
- Unit test — one function, class, or module in isolation. Its dependencies are replaced with stubs or fakes. Runs in milliseconds, and when it fails it points at exactly one small thing. The trade-off: it can't see problems that only appear when units are wired together.
- Integration test — several units running together, usually crossing at least one real boundary: a database, an HTTP client, a message queue, the file system. Slower than a unit test, but it catches the class of bug where each piece is correct on its own and the connection between them is wrong — a mismatched field name, a wrong content type, an assumed ordering that doesn't hold.
- End-to-end (E2E) test — the whole system from the outside, typically a real browser driving the real UI against a real (or realistic) backend. The slowest and most brittle kind, and the closest automated proxy for "does this actually work for a user." Because it's expensive, you want relatively few of these, aimed at the journeys that matter most.
The boundaries blur in practice — an "integration test" that spins up most of your services and hits them over HTTP is doing a lot of what an E2E test does. Don't argue about the label; agree on what the test covers and what it costs.
Test purpose: smoke, regression, acceptance
Where scope is about how much, purpose is about why the test exists.
- Smoke test — a shallow, fast check that the system isn't completely broken. "Does the app boot? Does the home page load? Can a user log in?" Run it first; if it fails, don't waste time on the deeper suite. Named after the hardware-testing practice of powering on a board and seeing if smoke comes out.
- Sanity test — a narrow, slightly deeper check that one specific change actually works, run after a small fix. Smoke is wide and shallow; sanity is narrow and focused. See smoke vs sanity.
- Regression test — locks in behaviour that used to work so a future change can't silently break it. Most of a mature suite is regression tests; every bug you fix should leave one behind.
- Acceptance test — checks a feature against its stated requirements, often phrased in business language and sometimes written or reviewed by non-engineers. Answers "does this meet the acceptance criteria we agreed on?"
The words for when tests go wrong
- Flaky test — passes and fails on the same code under the same conditions, without anything changing. Usually caused by timing (acting before the app is ready), test-order dependence, or shared mutable state. Flaky tests are corrosive: they train the team to rerun red builds instead of investigating them, and that habit lets real failures through too. See why E2E tests get flaky.
- False positive — the test fails but nothing is actually broken (a flaky test, a too-strict assertion).
- False negative — the test passes but something is broken (a weak assertion, over-mocking, a gap in coverage). More dangerous than a false positive, because it creates false confidence.
These two terms get used both ways in practice; this series follows the statistical convention above — a positive is the failure signal firing. See false positives vs false negatives.
Supporting cast
- Fixture — a known starting state a test sets up before it runs: seeded data, a logged-in user, a configured feature flag. Good fixtures make tests self-contained; shared ones cause order-dependent flakiness. See fixture.
- Mock / stub / fake — stand-ins for a real dependency. A stub returns canned answers; a mock also records how it was called so the test can assert on that; a fake is a lightweight but genuinely working implementation (an in-memory database). See mock vs stub vs fake.
- Assertion — the specific, checkable claim a test makes about the result. A test with no assertion isn't a test — it just confirms the code ran without throwing.
- Test case vs test scenario — a scenario is a high-level thing to verify ("a user can reset their password"); a case is the detailed, step-by-step procedure that verifies it. See the distinction.
The takeaway
Scope (unit / integration / end-to-end) is about how much of the system a test touches. Purpose (smoke / regression / acceptance) is about why it exists. The "when things go wrong" words — flaky, false positive, false negative — describe failure modes of the suite itself, not the product. Keep this page bookmarked; Part 3 uses all of it to answer the next question: how much of each kind of test do you actually want?