Manual or Automated Testing: When to Use Which

Manual and automated testing do different jobs. A practical guide to what each is good at, when automation pays off and the mistakes that waste it.

“Should we test manually or automate?” comes up in almost every project we start. It sounds like a choice between two options, but it isn’t. Manual and automated testing do different jobs. Automation repeats the checks you already know you need, every time, without getting bored. A person testing by hand finds the things nobody thought to check.

The real question is which tests belong in which pile. This guide is how we decide.

What manual testing is good at

Manual testing is a person using the software with a goal and paying attention. It is the right tool when:

  • The feature is new or still changing. While the design and the requirements move every week, a script written today is out of date tomorrow. Test it by hand until it settles.
  • The check needs judgement. “Is this confusing?”, “Does this error message make sense?”, “Does the layout look broken on this phone?” A script can’t answer those well.
  • You are exploring. Exploratory testing means poking at the product on purpose: odd inputs, unusual orders of steps, two tabs at once. It finds the bugs nobody wrote a test case for.
  • The check runs once. A one-off data migration or a rarely used admin screen may not be worth automating.

What automated testing is good at

Automated tests are code that drives the app and checks the result. They are the right tool when:

  • The same check runs again and again. Regression testing, which confirms that what worked last release still works, is the classic case.
  • The path is critical. Sign-up, log-in, checkout and payment should be checked on every change, not when someone has time.
  • There are many combinations. Ten discount codes across three customer types is thirty cases: tedious by hand, trivial in a loop.
  • It has to run on every commit. In a CI pipeline, tests run before anything is deployed, so a broken change never reaches users.

A simple rule for deciding

Automate a test when all three are true:

  1. It is repeated often, at least every release.
  2. It is stable. The feature isn’t being redesigned next sprint.
  3. The result is clear pass or fail. A total is right or wrong, a page loads or it doesn’t.

If any of the three is missing, test it by hand for now. Revisit it when the feature settles.

Mistakes that waste automation

Automating too early. Scripts written against a screen that is still changing break with every redesign, and the team spends its time fixing tests instead of finding bugs.

Testing everything through the UI. End-to-end tests that click through the browser are slow and the most fragile kind. Most checks belong lower down: unit tests for business logic, API tests for the server, and a small number of end-to-end tests for the critical paths. This is the “test pyramid”: many fast tests at the bottom, few slow ones at the top.

Living with flaky tests. A test that fails at random teaches the team to ignore red builds. Fix it or delete it. A suite nobody trusts is worse than no suite.

Dropping manual testing altogether. An automated suite only checks what someone imagined when they wrote it. Without exploratory testing, the bugs nobody imagined go straight to production.

The cost question

An automated test costs more the first time: someone has to write it and keep it working as the product changes. It pays that back every time it runs. So the maths depends on how often it runs. A check you need once or twice a year is cheaper by hand. A check you need on every release, across several browsers, is far cheaper automated.

Here is a typical candidate: a pricing rule checked for many inputs, which nobody wants to retype before every release.

import { expect, test } from '@playwright/test';

const cases = [
  { code: 'WELCOME10', subtotal: 200_000, total: 180_000 },
  { code: 'FREESHIP', subtotal: 200_000, total: 200_000 },
  { code: 'EXPIRED', subtotal: 200_000, total: 200_000 },
];

for (const { code, subtotal, total } of cases) {
  test(`discount ${code} on ${subtotal}`, async ({ request }) => {
    const response = await request.post('/api/cart/quote', { data: { code, subtotal } });
    expect((await response.json()).total).toBe(total);
  });
}

It runs through the API, not the browser, so it is fast and doesn’t break when the checkout page is redesigned.

How we combine both on a release

On a typical release we do it in this order:

  1. Analyse the business and agree on the critical paths.
  2. Write the test cases.
  3. Test each feature, by hand while it is new and automated once it is stable.
  4. Run the automated regression suite.
  5. Exploratory testing by hand, looking for what the cases missed.
  6. Release integration tests, then user acceptance testing (UAT) with the client.
  7. A check on production right after deployment.

Automation carries the repeated checks in steps 3, 4 and 6. People do the thinking in steps 1, 5 and 7.

Which tool?

For browser automation the three common choices are:

  • Playwright: Chromium, Firefox and WebKit (Safari’s engine) from one API, with built-in waiting and parallel runs. A strong default for new projects.
  • Cypress: a very friendly test runner for front-end teams, with fast feedback while writing tests. Its Safari support is limited.
  • Selenium: the longest-standing option, built on the WebDriver standard, with the widest choice of languages. It fits teams that already have Java or C# suites and test grids.

The tool matters less than the choices above it. A well-chosen set of tests in any of the three beats a large, flaky suite in the “best” one. We work with all three and usually stay with whatever the team already uses.

The short version

  • Manual and automated testing aren’t rivals. They do different jobs.
  • Test by hand when something is new, changing, needs judgement or runs once.
  • Automate checks that are repeated, stable and clearly pass or fail, starting with the critical paths.
  • Keep most automated tests below the UI, and fix or delete flaky ones.
  • Always keep some exploratory testing.

Launching an app built with AI tools? See also how to test an app built with AI before launch.

Have a release coming up?

Contact us