Unit tests (the base)

A unit test checks one small piece of code — a single function or class — in isolation, with no real database, network, or browser involved. Unit tests are fast (thousands can run in seconds), cheap to write, and pinpoint failures precisely. A healthy project has a lot of these.

Integration tests (the middle)

An integration test checks that several pieces work correctly together — a function that talks to a real database, or two internal services calling each other. These catch problems unit tests can't see (the pieces individually work, but not together), at the cost of being slower and a bit more involved to set up.

End-to-end / browser (UI) tests (the top)

An end-to-end test drives a real browser exactly the way a real user would: it opens a page, clicks buttons, fills in forms, and checks that the page responds correctly. This is what browser automation tools like Selenium WebDriver, WebdriverIO, and Playwright do — and it's what every example on this site demonstrates. These tests sit at the top of the pyramid: there are fewer of them, but each one gives high confidence, because it exercises a real user journey through the real, assembled application — front end, back end, and everything wired together — rather than one isolated piece of it.

Examples you can ask AI

  • Can you explain the automatic testing pyramid simply — what's the actual difference between a unit test, an integration test, and an end-to-end test?
  • My project has plenty of end-to-end browser tests but almost no unit tests — is that actually a problem, and how would I start fixing the balance?
  • How do I decide, for a specific new feature, which layer of the pyramid a new test belongs in rather than defaulting to another end-to-end test?

Next: what is browser testing? →