Get in Touch
About Us Insights Newsroom Gallery Why AtomicNorth Get in Touch

Tests that fail
for a reason

Test automation, regression suites and CI integration, including the harder judgement about which tests are worth writing and which will cost more to maintain than the bugs they catch.

A test that fails intermittently is deleted or fixed the week it starts, because a suite people rerun until it passes is worse than no suite.

LayersUnit to end to end

Weighted so most coverage sits where it is cheap and fast, not all at the browser.

ToolingYours where it works

We operate an existing framework rather than replacing it to suit our habits.

IntegrationIn the pipeline

A suite that only runs when someone remembers is documentation, not a safety net.

DisciplineFlakiness is a defect

An unreliable test is raised as a bug against the suite, with an owner and a date.

What we automate

Coverage where it actually pays

Automation is sold as a coverage percentage and lived as a maintenance bill. The work that matters is choosing what to automate, keeping the suite fast enough that people run it, and refusing to tolerate tests nobody believes.

Regression suites

Automated coverage over the flows that must not break: the transaction that takes money, the batch that closes the period, the login everything depends on.

Scope is chosen from incident and defect history rather than from a feature list, because the past is the best available guide to where this system breaks.

A suite that catches the failures you have actually had.

Unit and integration testing

Test coverage inside the codebase where feedback is fast: business logic, edge cases, boundary conditions and the interfaces between components.

Pushing coverage down the layers is what makes a suite quick. A pipeline that takes half a working day to report is a pipeline people learn to bypass.

Failures that point at a function, not at a screen.

API and interface testing

Contract tests on the interfaces between services and to third parties, including the error responses and timeouts that only appear in production.

Interfaces are tested for behaviour when the far end is slow, wrong or absent, which is the case teams write last and hit first.

Integration breakage caught before a release, not during.

End to end and browser testing

A deliberately small set of flows through the real interface with Playwright, Cypress or Selenium, kept stable with proper selectors and no timing guesswork.

This layer is capped on purpose. Every flow added here is a maintenance commitment for as long as the interface keeps changing.

A short, trusted set of flows rather than a slow one.

Performance and load testing

Load profiles built from real usage patterns, run against production-shaped data, with the results traced to the component that gave way.

A load test on an empty database measures the wrong system, and a result without a bottleneck named is a number rather than a finding.

A limit you have measured and can point at.

Taking over an untested codebase

Characterisation tests around current behaviour first, then coverage extended outward as the code becomes safe to change.

Existing behaviour is captured before anything is corrected, including behaviour that turns out to be wrong. Those get reported, not silently fixed.

A codebase that can be changed without holding its breath.

How a testing engagement runs

StepOneAssess

What exists, what runs, what is trusted: the current suite, its pass history, how long it takes and how often people ignore it.

Most estates have a suite. The useful question is not whether it exists but whether anyone changes their plans when it goes red.

You receive:

A coverage and risk picture

Defect and incident history mapped against current coverage, the flakiest tests named, and the gaps ranked by what an escape costs.

Yours to keep, and usable as a plan whether or not we do the work.

StepTwoHarness

A pipeline the suite runs in, test data that can be recreated, and environments that reset to a known state rather than drifting.

Unreliable test data causes most of what teams describe as flaky tests. Fixing the data is duller than fixing tests and works better.

You receive:

A working harness

Suite running on every change with results visible, repeatable test data, and environment reset automated rather than done by hand.

Runtime measured from the start, because a suite gets slower every week unless somebody is watching.

StepThreeAutomate

Coverage built in priority order from the assessment, weighted low in the stack, with the browser layer kept to the flows that justify it.

Manual testing is not eliminated. Exploratory testing finds a class of problem automation never will, so it is planned rather than displaced.

You receive:

Coverage in priority order

Tests delivered against the ranked list, each one reviewed for reliability before it joins the suite, with the trade-offs stated.

Where a test is not worth automating we say so and record the reason instead of quietly writing it anyway.

StepFourOperate

Steady state: suite maintained alongside the application, failures triaged the day they appear, and escapes fed back as new coverage.

A suite is a codebase. Left unowned it rots faster than the application it tests, and it takes the team's trust with it.

You receive:

A maintained suite

Suite runtime, reliability and failure causes reported on a cycle, with every escape to production reviewed for the missing test.

Tests that no longer earn their maintenance are retired deliberately rather than left to fail and be ignored.

01
Coverage

What is tested, and where it runs

The last column is the one that separates a real suite from a nominal one. A test that does not run automatically will eventually not run at all.

Automation Testing Services coverage
LayerToolingScopeWhen it runs
Unit JUnit, pytest, Jest, xUnitBusiness logic, boundaries, edge cases inside the codebaseEvery commit
Integration Framework test harnesses, containersComponent boundaries, persistence, messaging behaviourEvery commit
API REST and contract testing toolsInterface contracts, error paths, timeout and retry behaviourEvery build
End to end Playwright, Cypress, SeleniumA capped set of critical flows through the real interfaceEvery build to a test environment
Performance JMeter, k6, GatlingLoad profiles from real usage against production-shaped dataBefore release and on a cycle
Accessibility Automated checks plus manual reviewWCAG checks in the pipeline, keyboard and screen reader review by handEvery build, reviewed per release
Exploratory Manual, plannedUnscripted testing of new and changed areas by a personPer release
Flakiness

A suite people rerun until it passes is worse than no suite

The failure mode is predictable. A few tests start failing occasionally, the team learns that rerunning usually clears it, and rerunning becomes reflex. From then on a red build carries no information, and the real regression sails through behind a shrug.

So flakiness is treated as a defect against the suite with an owner and a date, not as background weather. The fix is usually test data or environment state rather than the test itself, and a test that cannot be made reliable is deleted. A smaller suite everybody believes beats a large one nobody does.

Ask for a test assessment
  • Reliability trackedPass history per test is recorded, so an intermittent failure is visible as a pattern rather than remembered as a nuisance.
  • Fixed or removedAn unreliable test gets a defect with an owner and a date. If it cannot be made reliable it leaves the suite.
  • Runtime defendedTotal suite time is a reported number. When it grows past the point people will wait, coverage moves down the layers.

Applies to suites we build, and it is the standard we assess an existing suite against.

Questions we get asked

Before automating the testing

What coverage figure should we aim for?

None in particular, and a target number is the fastest way to a suite full of worthless tests. Coverage is a diagnostic, not a goal: it tells you which parts of the code no test touches, which is useful. What matters is whether the flows that would hurt you are covered, and that is answered by reading the defect history rather than by reading a dashboard.

Does automation replace our manual testers?

No, and engagements sold on that basis tend to disappoint. Automation takes the repetitive regression work, which is exactly the work humans are worst at doing carefully for the twentieth time. Exploratory testing, usability judgement and the instinct for where a change is likely to have broken something are not automatable, and they are what your testers should be spending their time on.

Can you automate against an application with no tests at all?

Yes, and it is a large share of what we do. It starts at the outside with characterisation tests around current behaviour, because that is the only layer available before the code becomes safe to change. Coverage then moves inward as refactoring becomes possible. Starting at the outside is a deliberate compromise, not the target state.

Should we replace our existing test framework?

Usually not. If a framework runs, is understood by your team and integrates with your pipeline, replacing it is a project with real cost and no new coverage at the end. We will recommend a change where the tool is abandoned upstream, cannot run unattended, or is the actual cause of the unreliability, and we will say which of those applies.

Who owns the tests when the engagement ends?

You do, and they live in your repositories next to the application code from the first test onward. A test suite held anywhere else is not a safety net, it is a dependency on us, and that is not a position worth engineering.

A suite youactually believe.

Start with a test assessment. It needs the code, the pipeline and the defect history rather than a contract, and it produces a ranked coverage plan you keep.

Get in touch Book a scoping call