Left-Shift & Right-Shift

37Left-Shift & Right-Shift Testing

What you will master here

  • What shift-left and shift-right actually mean
  • Practices that pull testing left (TDD, contract tests, pre-commit checks)
  • Practices that extend testing right (synthetic monitoring, chaos, observability)
  • Where SDET adds the most leverage at each end

37.1 The two halves

LEFT — find bugs earlier requirements · dev · pre-commit Traditional E2E QA / staging RIGHT — observe in prod monitoring · canaries · chaos Quality is owned across the whole lifecycle, not just QA phase Bug found left = ~1× cost · same bug in prod = ~100× cost
Figure 16 — Shift-left finds bugs earlier; shift-right catches what slips through.

37.2 Shift-left practices

PracticeWhat it isSDET role
3 amigosPM, dev, tester refine each story together before codeSurface edge cases, define test data needs
Example mapping / BDDWrite acceptance criteria as concrete examplesDrive the conversation; convert examples to tests
TDD / dev-written unit testsTests before code, owned by devsCoach, review, ensure quality of unit tests
Pre-commit hooksLint, type-check, fast tests before pushMaintain hook config; add fast checks
Contract testing (Pact)Producer + consumer agree on API shape; test contract independentlyChampion the practice; own broker
Static analysis / lintingESLint, SonarQube, type checkersConfigure rules; gate PRs
Threat modellingFind security weaknesses in design phaseInject security-aware test cases
PR-level testsSmoke + targeted regression on every PRBuild the pipeline

37.3 Shift-right practices

PracticeWhat it isSDET role
Synthetic monitoringScheduled Playwright/REST checks against prodAuthor and own these "always-on" tests
Canary release / feature flagsRoll out to 1% before 100%; auto-rollback on errorsDefine gating metrics; partner with SRE
A/B testingCompare two variants on real trafficVerify the experiment instrumentation works
Chaos engineeringInject failures (latency, kill pods) to test resilienceAuthor chaos experiments and verify auto-recovery
Observability (logs, traces, metrics)See what prod is actually doingDefine SLIs / SLOs; alert on drift
Bug bash in prod-like environmentsTeam-wide exploratory testing of a buildOrganise, capture findings
User feedback loopsIn-app feedback, support ticket aggregationConvert recurring issues into tests

37.4 Synthetic monitoring with Playwright

// tests/prod-smoke.spec.ts — runs every 5 minutes in production
test('prod login still works', async ({ page }) => {
  await page.goto('https://app.acme.com/login');
  await page.getByLabel('Email').fill(process.env.SYNTH_USER!);
  await page.getByLabel('Password').fill(process.env.SYNTH_PASS!);
  await page.getByRole('button', { name: 'Sign in' }).click();
  await expect(page.getByText('Dashboard')).toBeVisible({ timeout: 10_000 });
});

test('prod checkout API is up', async ({ request }) => {
  const r = await request.get('https://api.acme.com/health');
  expect(r.status()).toBe(200);
});

Schedule via GitHub Actions cron, Datadog Synthetics, or Checkly. Page the on-call if a check fails twice in a row.

37.5 Contract testing with Pact (1-min mental model)

  1. Consumer (frontend) defines what it expects from the API.
  2. Consumer's tests use a mock that records the expectation as a "Pact" file.
  3. Pact file is published to a broker.
  4. Producer (API) replays the contract in its own tests — must match.
  5. If producer changes break the contract, producer's CI fails before deploy.

Result: frontend and backend evolve independently without integration surprises. Common in microservice orgs.

37.6 Feature flags + canaries

// Flag in code
if (await featureFlags.isEnabled('new-checkout')) {
  return <NewCheckout />;
} else {
  return <OldCheckout />;
}

// SDET checks both paths in CI
test('old checkout', async ({ page }) => {
  await page.context().addCookies([{ name: 'ff-new-checkout', value: 'off', url: '/' }]);
  /* ...assert old flow... */
});
test('new checkout', async ({ page }) => {
  await page.context().addCookies([{ name: 'ff-new-checkout', value: 'on', url: '/' }]);
  /* ...assert new flow... */
});

37.7 What "right-shift" looks like in practice

Module 30 — Shift Q&A bank

What does "shift-left" mean?
Move quality activities earlier in the development cycle — into design, dev, and pre-commit phases — so defects are found and fixed when they're cheapest. Examples: TDD, contract tests, pre-commit lint, BDD/example mapping.
What does "shift-right" mean?
Extend quality activities into production — synthetic monitoring, canary releases, feature flags, chaos engineering, observability. Catch what slipped past pre-prod testing, with minimal blast radius via gradual rollout.
Are shift-left and shift-right competing or complementary?
Complementary. Shift-left makes the test net tight before deploy. Shift-right makes the safety net wide after deploy. Both serve the same goal: detect issues fast, minimise impact.
What's contract testing and when does it pay off?
Consumer and producer of an API agree on a contract; each tests against it independently. Frontend doesn't need a real backend to test against, and backend can't break the frontend without its CI failing. Pays off heavily in microservice / large-org setups where teams move independently.
What is synthetic monitoring?
Scheduled tests that hit production from outside (or from a known location) on a cadence, alerting on failures. Like a heartbeat for critical flows. Lighter and faster than full regression — usually a few critical user journeys + API health checks.
What's a feature flag?
A switch in code that gates new behaviour. Deploys the code but keeps it off until you flip the flag. Enables canary releases (% rollout), instant rollback (without redeploy), and runtime A/B testing. SDETs test both flag states.
How do you test feature-flagged code?
Run the test suite twice — once with the flag on, once with it off. In Playwright, set the flag-controlling cookie/local-storage in a fixture. Don't let the test depend on the global default; explicitly configure both states.
What is chaos engineering?
Intentionally inject failures (kill pods, drop network packets, raise latency) into a controlled environment and verify the system stays usable. SDETs may author chaos experiments and add tests that assert auto-recovery / graceful degradation.
What's an SLO and why does an SDET care?
Service Level Objective — a measurable reliability target (e.g. "99.9% of API requests < 200 ms"). SDETs help define test coverage that backs the SLO and alerts that watch it in production. SLOs translate "is this app good?" into objective numbers.
One-sentence pitch for shifting quality both ways.
"Find bugs as early as possible (shift-left); catch the ones that slip through with minimal blast radius (shift-right). Owning quality across the lifecycle, not just the QA phase, is the SDET's leverage."