TecLeads TecLeads Blog
2026-07-24 · 8 min read

Test Automation That Still Works as the Team Grows

Two engineers reviewing code together on a laptop
qatest automationquality engineeringperformance testingci pipelines

A pull request goes red. The developer clicks rerun. It goes green. Everyone moves on.

That looks harmless until rerunning becomes the normal way to merge code. At that point, the test suite is no longer protecting the release. It is generating background noise, and the team has quietly learned to ignore it.

Test automation rarely collapses because nobody wrote enough tests. It collapses because ownership, execution time, test data, failure handling, and release decisions were never designed to survive team growth.

The strategy needs to scale before the test count does. This checklist is how I approach it.

Start with release risk, not a tool comparison

Buying another test platform will not tell you what deserves protection. Start by writing down how the product can hurt users or the business.

A payment calculation probably needs focused unit tests, API tests around provider behavior, and a small number of end-to-end checks. It does not need fifty browser scenarios that all log in, fill the same form, and fail when somebody renames a button.

This is where QA becomes quality engineering. The goal is not maximum coverage. The goal is useful evidence about whether a release is safe enough to ship.

Give every test an owner

Shared ownership often means nobody touches the suite until it blocks a release. Put ownership beside the code.

A central QA team should shape standards, provide tooling, and challenge weak coverage. It should not become a repair desk for tests written by everyone else.

Use CODEOWNERS where it helps:

/services/billing/ @billing-team
/tests/contracts/billing/ @billing-team
/tests/e2e/checkout/ @commerce-team @qa-platform
/performance/checkout/ @commerce-team @platform

Ownership must be visible and boring. If finding the owner requires archaeology in Slack, maintenance will lose.

Keep the fast path genuinely fast

As the team grows, more commits arrive and CI contention becomes a product problem. A ten-minute job does not merely cost ten minutes. It interrupts thought, encourages larger pull requests, and makes developers batch risky changes.

Do not split tests only by directory. Split them by purpose and expected duration. Pytest markers are simple and sufficient for many teams:

[pytest]
markers =
 smoke: critical release checks
 integration: tests requiring local dependencies
 slow: tests unsuitable for the pull request path

Then make each CI lane explicit:

pytest -m "not slow" --junitxml=reports/pr.xml
pytest -m smoke --junitxml=reports/smoke.xml
pytest -m slow --junitxml=reports/nightly.xml

A scheduled suite is not a dumping ground. Somebody still needs to read its failures before they fossilise.

Treat flaky tests as defects

A flaky test is not an inconvenience. It trains the team to distrust all failures, including the real one that appears during a bad release.

Retries can confirm that a failure is intermittent. They cannot make the test healthy. One controlled retry may help collect evidence, but a green result after retry should still be reported as flaky.

Most flaky tests come from a short set of engineering mistakes: shared state, uncontrolled clocks, asynchronous assertions with arbitrary sleeps, order dependence, external services, and selectors tied to presentation.

Replace this:

await page.waitForTimeout(3000);
await expect(page.locator('.toast-success')).toBeVisible();

With an assertion that waits for the actual condition:

await expect(page.getByRole('status')).toHaveText('Order confirmed');

The second version describes behavior. The first version hopes the build agent is having a good day.

Make test data disposable

Test environments become unreliable when every suite assumes a particular account, order, or database row already exists.

A useful test creates its world, performs the action, and leaves enough evidence to diagnose failure. It should not inherit last Tuesday's world from a shared staging database.

Containers help with local dependencies. Testcontainers can start a real PostgreSQL, Redis, Kafka, or compatible service for the test process. That is usually more faithful than mocking database behavior and more predictable than sharing a long-lived environment.

Mocks still belong at boundaries where the real dependency is costly, destructive, or outside your control. Just do not mock the code you are trying to prove.

Save evidence, not screenshots of blank pages

When CI fails, the first response should not be, "Can you reproduce it locally?"

Playwright traces are particularly useful because they show DOM snapshots, requests, console output, and each action around the failure:

use: {
 trace: 'retain-on-failure',
 screenshot: 'only-on-failure',
 video: 'retain-on-failure'
}

Artifacts need a retention policy, but failed runs should remain available long enough for the owning team to investigate them. A screenshot without logs or request details is often just photographic proof that something went wrong.

Put performance testing beside functional change

Performance testing performed just before a major release tends to discover architectural problems when they are most expensive to address.

A k6 threshold makes the expectation executable:

export const options = {
 thresholds: {
 http_req_failed: ['rate<0.01'],
 http_req_duration: ['p(95)<500'],
 },
};

Those values are examples, not universal targets. Choose thresholds from product expectations and observed production behavior. Then review them when the system or traffic model changes.

Make the pipeline state what it believes

A mature pipeline does not merely run tests. It turns their results into release decisions.

This is release confidence wired into the pipeline. Developers get quick feedback while changes are small. Broader checks protect integration and deployment. QA specialists improve the system instead of repeatedly executing the same scripts by hand.

If you only do one thing this week

Find the tests your team reruns without investigation. Give each one an owner, quarantine it visibly, and set a date to fix or delete it.

That small exercise exposes the health of the wider test automation strategy. It reveals whether failures are actionable, whether ownership is real, and whether the pipeline protects delivery or merely delays it. A suite that scales is not the one with the most tests. It is the one the team still believes when it says no.


If this is on your plate, TecLeads does exactly this as part of our QA & Test Automation work. If you'd like a second pair of eyes on your setup, book a 30-minute call or explore what we do.

📍 Tech Pulse · today's quick question 🟢 Level: Basic DevSecOps

What does shift-left security mean?

Pick an answer to see how other engineers voted.

Want a hand with this?

TecLeads helps engineering teams ship faster and more securely.

Book a 30-minute call

← All posts