QASimplifiedby AkashGet Free Interview Pack
← Back to Articles

Automation Foundations # 2 - UI, API or Unit: Where Should an Automated Test Live?

20 October 2026

Every automation team eventually hits the same wall.

The suite has grown to 800 UI tests. The nightly run takes four hours. Twenty tests fail every morning, and half of them pass on rerun. Nobody trusts the red anymore. Developers stop looking at the report, and the automation engineer spends Monday “fixing flaky tests” instead of adding coverage.

The tests aren’t usually the problem. The placement is.

Most struggling automation suites don’t fail because of bad tools or bad code. They fail because tests were written at the wrong layer. This article is about one decision that quietly shapes your whole automation strategy: where should this test live?

The three layers, in plain terms

Unit tests check one piece of logic in isolation, like a function, a class, or a calculation. They don’t touch a database, a network, or a browser. They run in milliseconds.

API (service) tests check the system’s behaviour through its interfaces. You send a request, check the response, and sometimes verify the side effects. There’s no browser, but real business logic, real validation, and often a real database are involved.

UI tests drive the application the way a user would: open a browser, click, type, read the screen. They prove that the whole stack works together from the user’s point of view.

All three are useful. They just answer different questions at very different prices.

The real cost of a test

When teams compare layers, they often think only about execution time. That’s the smallest part of the cost.

A test’s real cost includes:

  1. Writing time: how long it takes to create.

  2. Run time: how long it takes to give feedback.

  3. Failure diagnosis: how long it takes to understand why it failed.

  4. Maintenance: how often it breaks for reasons unrelated to a real bug.

  5. Trust erosion: what happens to the team when it fails falsely.

A unit test that fails usually points straight at the broken line. An API test failure gives you a status code, a payload, and a clear difference from what you expected. A UI test failure often gives you a screenshot and “TimeoutError: locator not visible.” That could mean a real bug, a slow environment, a changed CSS class, a backend outage, or a race condition.

That’s why UI tests cost more. It isn’t the browser. It’s how much uncertainty each failure carries.

The question that decides everything

Before writing any automated test, ask:

Where does the logic I’m testing actually live?

  • If the logic lives in a function or service class, test it at the unit level.

  • If the logic lives in how services talk to each other, such as contracts, auth, validation, or persistence, test it at the API level.

  • If the logic lives in what the user sees or does, such as rendering, navigation, client-side behaviour, or the full journey, test it at the UI level.

Then a second question:

What’s the cheapest layer that can catch this failure?

If a pricing bug can be caught by a unit test, catching it through the UI too doesn’t add confidence. It only adds cost.

A worked example: the pricing rule

Take a real-looking rule:

  • Orders above ₹5,000 get 10% off.

  • Premium members get an extra 5%.

  • The total discount can’t go above 12%.

A UI-heavy team would write tests like: log in as premium user → add items worth ₹5,001 → go to cart → check the discount label. Then repeat for ₹4,999, ₹5,000, non-premium, the cap, and so on. That’s 12 to 15 browser tests, each taking a minute or more and each depending on login, product catalogue, cart service, and frontend locators.

Here’s how a layered approach handles it.

Unit layer (most of the coverage):

  • Boundary values: ₹4,999 / ₹5,000 / ₹5,001

  • Member vs non-member

  • Cap enforcement: does 10% + 5% correctly become 12%?

  • Zero, negative, and very large cart values

  • Rounding behaviour

That’s about 15 tests that run in under a second.

API layer (integration confidence):

  • Does POST /cart/price apply the discount for a premium user token?

  • Does it ignore the premium discount for a regular user?

  • Is the discounted total saved correctly on the order?

  • What happens with an invalid or expired membership?

That’s 4 or 5 tests that run in a few seconds.

UI layer (user confidence):

  • One journey: a premium user checks out a high-value cart and sees the correct discounted total before payment.

That’s one test.

You end up with better coverage, failures that point to their cause, and a suite that finishes in seconds instead of half an hour.

“But the developers own unit tests”

Often they do. That doesn’t take QA out of the conversation.

A strong automation engineer:

  • Knows what unit tests already cover, so they don’t duplicate it through the UI.

  • Reviews unit test gaps during story refinement and PR review. (”Is the 12% cap covered?”)

  • Owns the API layer heavily. This is where QA gets the most value.

  • Treats UI automation as the final proof, not the main safety net.

The shift is from “I automate test cases” to “I make sure every risk is covered at the right layer.”

What actually belongs in the UI

None of this makes UI automation less important. It makes it more deliberate. Keep UI tests for:

  • Critical user journeys: sign-up, login, checkout, payment, and the core flows that make money.

  • Client-side logic: dynamic forms, conditional fields, front-end validation.

  • Rendering correctness: is the right data shown in the right place?

  • Cross-browser or device risk, where it genuinely matters.

  • Smoke checks that prove the deployed stack is wired together.

A healthy suite might have dozens of UI tests, not hundreds, and each one should justify its place.

Common anti-patterns to watch for

  • UI tests used as data setup. Creating 10 users through the sign-up page before every test. Use APIs or seed data instead.

  • Verifying business rules through labels. Reading “Discount: ₹500” off the screen to validate a calculation.

  • Duplicating every API test as a UI test “for completeness.”

  • No API layer at all, where the team jumps straight from developer unit tests to Selenium or Playwright.

  • Retrying flaky UI tests instead of moving them down a layer.

If you see these, you’ve found where your maintenance hours are going.

A simple decision checklist

Before you automate, run through this:

  1. What risk am I protecting against?

  2. Where does that logic live?

  3. What’s the lowest layer that can reliably catch this failure?

  4. Is this already covered at another layer?

  5. Does the user’s experience add risk that lower layers can’t see?

If question 5 is “no,” the test probably doesn’t belong in the UI.

The takeaway

The Test Pyramid isn’t about ratios. It’s about economics. Every test spends something: time, stability, trust. Good automation engineers place each test where it gives the most confidence for the least cost.

So the next time you start writing a browser test, stop and ask:

“Is the UI really where this risk lives?”

Often it isn’t. Moving that test down a layer may be the most valuable automation work you do this sprint.


Next Tuesday: What Should You Automate First? A Practical Selection Framework