Shift Left Testing — Why We Moved Testing From the End to the Start
We started with E2E automation on Staging: slow, flaky, and run by hand. Shift Left changed the whole equation — how it happened, and the skills it asks of you.
When automation first arrived, we put the tests at the end of the chain: development finishes, it gets deployed to Staging, and then we run the tests.
And it worked — but it came with a set of pains that anyone who worked back then knows well. Shift Left is the solution that came out of exactly those pains.
How test automation started
The picture was roughly the same everywhere, and it's still like this in many companies and countries today:
- Selenium with Java — the most famous duo, hands down
- A completely separate project, in its own Repository, far from the product code
- Tests running against a real environment like Staging
- And running them was manual: the tester opens the project and hits Run
And it really was a big leap. For the first time we had a Regression that ran overnight instead of taking a week. But over time, the problems showed.
The pains everyone lived through
The tests were Flaky. Passing one time and failing the next, with the same code. Sometimes the cause was the environment itself — a service being slow or returning the wrong thing — and sometimes the test itself was written in a fragile way.
Test data was a nightmare. You need a user in a specific state, and an order in a specific condition. In big companies this alone was a battle: who creates the users? Who cleans them up afterwards? And what happens when someone else uses the same user at the same time?
Running stayed manual, with maintenance before every run. Every UI change broke Locators, so before you could run anything you had to go and fix them.
Everything was E2E. There were no levels — every check, however small, went through the entire system.
And in the end: re-run until it passes. Worse still, after all that, you'd still end up checking a few flows by hand because some tests didn't make it through the run.
Then came Shift Left
The idea is simple: instead of testing at the end, push testing down and earlier — to the Unit and Integration levels, while a bug is still cheap and easy to find.
To make that happen, new tools and practices emerged that changed how the work looks:
Separate the frontend from the Backend
Instead of testing the frontend while it's wired to all the real services, you test it against a Mock Server that returns whatever responses you want. The side effect turned out to be the most important part: you could now write these tests in the same language as the frontend, and in its own Repository.
That point alone solved half the problem. The test now lives right next to the code it tests, so any change that breaks a test shows up in the same Pull Request — not a week later in another project.
And separate the Backend too
Exactly the same logic: you test the Backend on its own, with a temporary in-memory database that's created at run time and wiped afterwards, and data you plant yourself (Seeding) instead of begging for ready-made users on a shared environment.
And just like that, the question "who creates the test users?" disappeared — you do, on every run, from scratch.
And that's where CI/CD was born
Once everything was in one place — the code, the tests, and the Mocks — you could run the whole chain on any machine: install the app, Mock everything external it needs, and run the tests.
Need users? Mock them. Need a specific response from a service? Mock it.
And that's what made the tests:
- Stable — no shared environment that someone else is messing with
- Fast — seconds instead of hours
- And most importantly: running on their own in the Pipeline, on every Pull Request, without anyone pressing a button
The shape of the pyramid after Shift Left
The rule of thumb: 90% of your coverage at the Unit and Integration levels, and only 10% E2E — limited to the most important flows: login, checkout, payment. The flows that, if they go down, take the product down with them.
What Shift Left asks of you as a tester
This isn't just a change of tools — it's a change of skills:
| Skill | Why you need it |
|---|---|
| Mocking and Mock servers | The whole idea rests on it: isolating what you're testing from what you're not |
| Docker | The tool whose usage exploded in this era — it lets you run any app on any machine exactly the same way |
| Test design | Knowing what gets tested at which level, and resisting the temptation to test everything E2E |
| Synthetic Transactions | Tests that run on Production itself for the most important flows |
That last point deserves a pause. Synthetic Transactions are small tests that run against the live environment every few minutes and execute a critical flow — for example: log in, add a product to the cart, start checkout. And when one of them fails, that's an alarm for the whole team that there's a real problem on Production that needs immediate action — not a ticket that goes into the Backlog.
That way you have both ends covered: before the code ships, and after it ships.
A small example that explains the whole idea
Let's say there's a bug in the discount calculation: when the order value is zero, the discount comes out as a negative number.
The old way: the bug reaches Staging, and you catch it with an E2E test a week later. The test tells you "the checkout page shows the wrong number" — and that's it. Then someone has to open the Logs, trace the request, get to the responsible service, and find the function. Half a day at least, spread across several people.
With Shift Left: a unit test on the discount function fails within two seconds, on the developer's machine, before the code even reaches a Pull Request. And the failure message tells you the function name, the expected value, and the value that came back.
The exact same bug. The difference is where you caught it, and that difference multiplies the deeper down the chain it gets.
In the end
Shift Left isn't just testing early and calling it a day. It's moving testing to the cheapest place where you can find the bug. A bug you catch with a unit test costs you minutes; the same bug, once it reaches Production, costs you meetings, tickets, and apologies.
And notice a pattern that keeps repeating: every shift in the history of testing — from manual to automation, and from automation to Shift Left — didn't eliminate the tester, it just raised the bar on the skills expected of them. The people who learned Mocking, Docker, and test design when they came out are the ones designing the whole system today.
And the bar is about to rise again, right now. But that's a story for another article.
