There’s a wall every developer eventually runs into.
“Unit tests, integration tests, UI tests… what’s the difference?”
Let me give you the conclusion first.
The three tests differ in scope. Unit tests check a single function, integration tests check connections between modules, and UI tests verify the entire user-facing screen flow.
The guideline for deciding how to combine these three is the test pyramid. Today, I’ll explain the concept simply, along with my own experience.
Let’s start with the key summary
Here’s a quick summary for busy readers.
- Unit test: Verify one function or class. Write many, and keep them fast.
- Integration test: Verify that multiple connected modules work correctly. Use a moderate number.
- UI test: Verify the complete flow by interacting with the real screen. Keep them slow and few.
- Test pyramid: Build a wide base of unit tests and a narrow top of UI tests.
Remember these four lines and you’ll understand half of it. Now let’s unpack each one.
Unit, integration, and UI tests: what’s the difference?
This is the most confusing part, so let’s start with an analogy.
Imagine that you’re building a car.
A unit test checks whether a single screw or bolt meets its specifications. It’s a very small unit.
An integration test checks whether the engine and transmission work together properly after being connected.
A UI test means getting into the finished car, starting it, and taking it for a drive.
Here’s the comparison in a table.
| Category | Scope | Speed | Number written |
|---|---|---|---|
| Unit test | One function or class | Very fast (ms) | Many |
| Integration test | Module integration | Moderate (seconds) | Moderate |
| UI test | Entire user flow | Slow (tens of seconds) | Few |
The key difference is how broadly each test looks.
The broader the scope, the closer the test is to real usage—but it also becomes slower and harder to maintain.
What unit tests feel like
A short example will make this clearer than words alone.
Below is a unit test that focuses on verifying one function that adds two numbers.
// Unit test for verifying only the addition function
func add(_ a: Int, _ b: Int) -> Int {
return a + b
}
@Test func Addition_2_to add_3is_5() {
#expect(add(2, 3) == 5)
}
You don’t need an external database or a screen. You isolate and check just one function.
That’s why execution finishes in the blink of an eye. Even hundreds of tests take only a few seconds.
I write the most unit tests because they’re so fast. I can change the code and check it immediately.
What is the test pyramid?
Now we come to today’s main topic: the test pyramid.
It’s a concept Mike Cohn presented in his 2009 book, 『Succeeding with Agile』. The guideline is to stack tests in a triangle.
- Bottom (wide): Unit tests — the most
- Middle: Integration tests — a moderate number
- Top (narrow): UI tests — the minimum
Why this shape?
Tests get faster and cheaper toward the bottom. Running thousands of unit tests is no burden.
UI tests, by contrast, are slow and can break easily when the screen changes even slightly. Their maintenance cost is high.
Use lots of cheap, fast tests and fewer expensive, slow tests. That’s the whole test pyramid.
If you build the pyramid upside down, it’s called the “ice cream cone” antipattern. You end up with lots of UI tests and no unit tests—a recipe for being held back by slow, fragile tests.
So how should we choose the ratio?
This is something many people wonder about.
A commonly cited guideline is roughly 70% unit : 20% integration : 10% UI.
However, this is not an absolute rule. Adjust it flexibly according to the project.
For example, for a backend API server, increasing the share of integration tests is practical. Even organizations like Google emphasize maintaining the pyramid shape rather than hitting exact numbers.
Let me share one more piece of advice from my own experience.
Don’t obsess over the numbers. What matters is building the habit of checking whether you rely too heavily on slow, fragile tests.
Frequently asked questions (Q&A)
Q. Are E2E tests and UI tests the same?
They’re used almost interchangeably, but strictly speaking they differ. E2E (End-to-End) means verifying the entire flow from the user’s perspective, while UI tests focus specifically on interacting with the screen. In practice, the terms are often mixed.
Q. If we write good integration tests, can we skip unit tests?
I don’t recommend it. Integration tests make it difficult to pinpoint where a problem occurred. Unit tests are needed to narrow down the cause quickly.
Q. Do we need to write all the tests from the start?
No. I recommend starting with unit tests for the core logic. I’ve often seen people burn out trying to build a perfect pyramid from day one.
The differences between these three may seem abstract on the page, but writing the code yourself makes them intuitive.
Start by adding a unit test to one small function using what you learned today. As you build that intuition, the rest will follow naturally. You’ve got this!

