Shift-Left and Shift-Right Testing

Shift-left and shift-right describe where testing sits on the timeline of a change. Shift-left moves testing earlier: reviewing the user story, agreeing acceptance tests before coding, running static analysis on every pull request. Shift-right extends testing past the release: watching production signals, showing a feature to 5% of users first, running controlled experiments.

A tester who asks "is the discount taken before or after VAT?" in refinement is shifting left. The same tester comparing a canary’s error rate with the other users after the release is shifting right. Neither replaces the testing in between.

Why it matters

A defect caught in a story review costs a conversation. After release, the same defect costs a fix, a redeploy, support time, sometimes refunds, and some of the users’ trust. Shift-left prevents defects and finds the rest while the change is still small.

But no test environment fully reproduces production: real traffic, real data, every device and every third-party service. Some failures appear only there, and without shift-right practices users notice them first. For a tester, testing stops being a phase at the end and becomes work across the whole lifecycle.

Shift left: test before and while the code is written

The ISTQB Foundation syllabus (CTFL v4.0) describes shift-left as testing earlier, without waiting for the code to be implemented or the components integrated, and stresses that later testing must not be neglected. It is the working form of the principle that early testing saves time and money. Besides the practices below, the syllabus lists CI, and better still CD, for fast feedback on every change, as in the previous lesson, and non-functional testing, such as performance, started at the component level where possible. It also names the price: extra training and effort early, expected to pay back later, and shift-left needs stakeholders who are convinced of it and support it.

  • Early reviews: testers review stories, acceptance criteria and designs from a testing point of view. This is static testing, and it finds ambiguities, gaps and contradictions before any code exists.
  • TDD (test-driven development): a developer writes a failing unit test, then just enough code to pass it, then refactors both, improving their structure without changing what they do.
  • ATDD (acceptance test-driven development): acceptance tests are derived from the acceptance criteria before the feature is built. In BDD (behaviour-driven development), such examples are written as Given/When/Then, like the scenarios below.
  • Static analysis: tools examine source code without running it and report undefined variables, unreachable code, coding-standard violations and some security weaknesses, usually on every pull request in CI.
Feature: Promo code at checkout

  Scenario: A valid percentage code reduces the total before VAT
    Given a cart totalling 150.00 SAR before VAT
    And the active code "SAVE10" gives 10% off
    When the shopper applies the code "save10"
    Then the discount is 15.00 SAR
    And the total before VAT is 135.00 SAR

  Scenario: An expired code is refused
    Given the code "WINTER25" expired yesterday
    When the shopper applies the code "WINTER25"
    Then the message "This code has expired" is shown
    And the total does not change

Try it: Acceptance Criteria Generator Try it: Requirements → Test Cases

Shift right: keep testing after the release

Shift-right is an industry term, not an ISTQB Foundation one; some teams call part of it "testing in production". Only production has real traffic, real data and every device, so the aim is to limit the damage of defects that get through and to learn what earlier testing missed, never to test on users instead of before them.

  • Monitoring: dashboards and alerts on what users experience. The four golden signals from the DevOps for testers lesson, taken from Google’s SRE book, are latency (how long requests take), traffic (how much demand reaches the system), errors (the rate of failed requests) and saturation (how full its resources are). Add business signals such as orders per hour, because some defects raise no error at all.
  • Canary release: the change first reaches a small share of users, and its signals are compared with a control group on the old version over the same period. If the canary is worse, it is rolled back before most users see it.
  • Feature flags: new code is deployed switched off, then turned on for a group or a percentage of users without a redeploy. Test both flag states and the switch between them.
  • A/B tests: two working variants run side by side on randomly split users and are judged by a metric agreed in advance. The tester checks the experiment is wired correctly; the product owner and analysts judge the result.
  • Chaos experiments: the team injects a realistic fault, such as a slow dependency, to test the hypothesis that the system keeps behaving normally. Experiments start small and can be stopped at once.

Try it: API Health Checker Try it: API Response Comparator

Worked example: a promo-code field from story to production

An online store adds a promo-code field to checkout; prices are in SAR with two decimals. The figure shows the feature on both sides of the release.

A promo-code field on both sides of its release: review, ATDD, TDD, static analysis and CI before it; a staff flag, a 5% canary, monitoring, an A/B test and a chaos experiment after it.
  1. Before release: shift left

    Prevent defects and find them while they are cheap to fix

    1. 1Story reviewStacking, case, VAT and rounding answered before coding
    2. 2Acceptance tests firstATDDAgreed Given/When/Then examples
    3. 3Unit tests firstTDD10% of 99.99 SAR must give 10.00
    4. 4Static analysis and reviewQuery built from the typed promo code → parameterised
    5. 5CI pipelineUnit, API and acceptance tests pass

      Gate: Deploy: in production with promo_codes off

  2. After release: shift right

    Limit the damage and learn from real use

    1. 6Flag on for staffRelease to users begins (staff, then 5%); smoke check with a test account
    2. 7Canary: 5% of shoppersError, latency and checkout rates vs the other 95%

      Gate: No rollback criterion met

    3. 8MonitoringEscape: one platform’s keyboard adds a space after the codeCaution
    4. 9A/B testVisible field vs a “Have a code?” link
    5. 10Chaos experimentSlow promo service: a clear message, and payment still works

Back to step 2 The escape becomes a new acceptance test: a code with spaces is accepted

Illustrative order: after the release, monitoring runs throughout, and experiments are scheduled once the feature is stable.

  • Review: the tester asks whether a code can be combined with free delivery, whether codes are case-sensitive, and whether the discount is taken before VAT and how it is rounded. The answers go into the acceptance criteria.
  • ATDD and TDD: the agreed examples become acceptance tests like the scenarios above (note save10 in lower case: the team agreed that codes are not case-sensitive). The developer writes unit tests first, including 10% of 99.99 SAR, which under the agreed rounding to the nearest 0.01 must give 10.00, not 9.99.
  • Static analysis: the analyser flags a query built by pasting the promo code the shopper typed into the SQL text, which would let a crafted promo code change the query itself (SQL injection). The reviewer asks for a parameterised query, which passes the promo code as data, before the merge.
  • Flag and canary: the code is deployed with promo_codes off, switched on for staff, who smoke-check it with test accounts, then for 5% of shoppers. Promo errors, latency and completed checkouts are compared with the other 95% as rates, not raw counts, against rollback criteria written in advance.
  • Escape: monitoring shows "invalid code" errors rising on one mobile platform, whose keyboard adds a space after the code. The fix now removes leading and trailing spaces, and the tester adds an acceptance test for codes with spaces: the finding moves left.
  • Experiments: an A/B test compares a visible field with a "Have a code?" link by completed checkouts, the metric agreed in advance. A chaos experiment slows the promo service to test the hypothesis that checkout, instead of hanging, says the code cannot be checked right now and still lets the shopper pay.

Try it: Percentage Calculator

Balancing both sides

The two sides are complements, not alternatives. Left-side work is cheap and prevents defects, but it tests the team’s assumptions; right-side work sees reality, but whatever it finds has already reached someone. Set the weighting for each change by risk.

  • Weight left when a failure would be severe or irreversible: payments, data migrations, privacy, security. A rollback does not refund a wrong charge.
  • Weight right when only real use can answer the question: real load, the full range of devices, which design users prefer.
  • Close the loop: for every escaped defect, add the missing test, review question or static-analysis rule.
  • Test in production only on systems your team owns or has written permission to test, with test accounts, no real personal data and a way to stop at once.

Try it: Risk-Based Test Generator

Common mistakes

  • Shifting left in name only: receiving the story earlier but still writing test scripts at the end, instead of asking the questions that change the story before coding.
  • Treating shift-right as permission to release untested code. Production catches what pre-release testing could not see, not what it skipped.
  • Testing a feature flag in one state only, or leaving old flags in the code, where each one doubles the combinations to test.
  • Judging a canary against yesterday’s numbers instead of a control group in the same time window, or starting a rollout without rollback criteria.
  • Switching static analysis off because it reports too much, instead of tuning the rules and failing the build only on the agreed ones.
  • Running production tests or chaos experiments without permission, with real customer data, or without a way to stop them.

The QA perspective

In refinement, sit with the product owner and a developer (some teams call this the three amigos), ask questions, propose concrete examples and turn the agreed ones into acceptance tests. On pull requests, read the static-analysis results and check that the unit tests cover the examples. Before release, help write the rollout plan: flag states, canary steps, the signals to watch, rollback criteria and who decides.

During the rollout, watch the dashboards with the developers; in the following days, read support tickets and error logs. Record the flag states you tested, the rollback criteria and each production finding with the test you added for it. That record shows the team where its testing should move next.

Practice exercise

Plan both sides of the release for delivery slots

Your task

A grocery app is adding delivery time slots. Read the user story below and plan its testing on both sides of the release: what you would do before the code is merged, and what you would do once it reaches production.

Keep the plan to one page. For every right-side activity, say what you will measure and which result would stop the rollout.

Material
User story:
As a shopper, I want to choose a delivery time slot at checkout
so that I am at home when the order arrives.

Rules:
- Slots are 2 hours long, from 09:00 to 21:00.
- A slot can be booked until 3 hours before it starts.
- Each slot takes at most 20 orders.
Steps
  1. Write three questions for the story review.
  2. Write two acceptance tests in Given/When/Then form, one of them negative.
  3. Write the rollout: the flag, the canary group, three signals to monitor and one rollback criterion.
  4. Write one chaos-experiment hypothesis, and say which side of the release you would weight more for this feature and why.
Show the model answer
Model answer

Review questions: Which clock sets the slot times and the 3-hour cut-off, the store’s time zone or the shopper’s device? What happens when two shoppers take the last place in a slot at the same moment? What does the shopper see if the slot fills up while they are paying?

Acceptance tests: Given the 15:00–17:00 slot has 19 orders and the time is 11:59, when a shopper books it, then the booking succeeds and the slot shows as full. Given the time is 12:01, when a shopper opens the slot list, then the 15:00–17:00 slot is not offered (negative). Whether a booking at exactly 12:00 is still allowed is one more question for the review; once it is answered, the developer can write that cut-off as a unit test first (TDD).

Rollout: deploy with the flag delivery_slots off, switch it on for staff, then for 5% of shoppers. Monitor booking errors, orders per slot (never above 20) and completed checkouts compared with the control group. Switch the flag off if any slot exceeds 20 orders or completed checkouts fall below the control group by more than the threshold agreed in the plan.

Chaos hypothesis: if the slot service is unavailable, checkout still completes with standard delivery and a clear message, and no order is lost. Measure completed checkouts and lost orders during the experiment, and stop it at once if any order is lost. Try it in staging first, then on a small share of production traffic.

Weighting: overbooking and time-zone errors are costly and hard to undo, so weight the left side for the capacity and cut-off rules. Whether shoppers use slots at all, and which slot layout works best, are right-side questions.

Frequently asked questions

Is shift-right just another name for testing in production?

Testing in production is part of it, but shift-right also covers monitoring, canary releases, feature flags, A/B tests and chaos experiments, which mostly observe and limit risk rather than run test scripts. It always adds to pre-release testing and never replaces it.

Does shift-left mean testers must write unit tests?

No. TDD is a developer practice. Shift-left means testing activities start earlier: the tester contributes questions, examples, acceptance tests and risk analysis, and reads static-analysis and unit-test results. Testers who code may pair with developers on tests, but that is a bonus, not the definition.

What is the difference between a canary release and an A/B test?

Both compare two groups over the same period (Google’s SRE workbook even describes canarying as effectively an A/B testing process), but they answer different questions. A canary asks whether the new version is safe: it compares health signals such as errors and latency with a control group, for a period that fits how often the team releases, and ends in a full rollout or a rollback. An A/B test asks which of two working variants serves a goal better: it compares a business metric chosen in advance and usually runs longer, so that enough users take part.

Can a small team without an operations department shift right?

Yes, in small steps: a smoke check right after each deploy, alerts on errors, a health check of the main endpoints, and a feature flag or a tested rollback for risky changes. Canary routing and chaos experiments need more infrastructure and can come later.

References

Practise with Mutqan tools

Convert a list of numbered requirements into traceable test cases with a requirement-to-test matrix.

Test Design

Score features by likelihood and impact, then generate a prioritised risk-based test plan.

Test Design

Check several API health endpoints at once and get status, latency and a pass/fail summary.

API Testing

Compare two API responses (e.g. staging vs production) and list every structural and value difference.

API Testing

Calculate percentages, percentage change, increase/decrease and what percent X is of Y.

Utilities

Go deeper

Your progress on this topic

Part of the QA Roadmap