Monorepo Testing Strategy: Bazel, Nx, Turborepo (2026)

Monorepos centralize multiple projects under one repository — shared dependencies, unified tooling, cross-project refactoring. Testing at scale becomes a discipline: run only what changed, parallelize

March 14, 2026 · 3 min read · Testing Guides

Monorepos centralize multiple projects under one repository — shared dependencies, unified tooling, cross-project refactoring. Testing at scale becomes a discipline: run only what changed, parallelize across projects, report clearly which project broke. This guide covers the strategy.

Why monorepos for testing

The flip side: tests at scale get slow, flaky, and hard to own if not managed well.

Tools

Nx (JS / TS focused)

Turborepo

Bazel

pnpm / yarn workspaces

Lerna

Test organization

Per-project


packages/
  ui/
    src/
    test/
    package.json
  api/
    src/
    test/
    package.json
  mobile-app/
    android/
    ios/
    test/

Each project has its own tests. Shared utilities in a dedicated test package.

Dependency graph awareness

api depends on shared-types. Change in shared-types → run api tests. Change in api → skip ui tests (no dependency).


nx affected --target=test --base=origin/main

Runs only what affected-or-dependent projects need.

CI parallelism

Shard across runners:


strategy:
  matrix:
    shard: [1, 2, 3, 4]
steps:
  - run: nx affected --target=test --parallel=4 --shard=${{ matrix.shard }}

4-way shard cuts wall-clock time 4x.

Caching

Local cache

Tests run once; subsequent runs use cache if inputs unchanged. Instant turnaround on unchanged code.

Remote cache

Cache shared across team and CI. First PR runs tests; second PR (same code) uses cache.


# Nx Cloud
nx connect-to-nx-cloud

Commercial: Nx Cloud, Turborepo Remote Cache, Bazel BuildBuddy.

Metrics

Track:

Visibility drives improvement.

Anti-patterns

Monolithic test run

npm test runs 10,000 tests every PR. Slow, expensive.

Fix: Affected-only.

Flaky tests not owned

Every project shares the flaky blame. Tests never fixed.

Fix: Owner in CODEOWNERS file; flake rate attributed per project.

Unified test framework forced

One project prefers Vitest, another Jest. Forced conformity causes friction.

Fix: Flexibility per project within unified orchestration.

Copy-paste setups

Each project has its own test config, config drifts, updates manual.

Fix: Shared config package; each project imports.

No isolation

Tests share state, one breaks another.

Fix: Per-test isolation (fresh DB, fresh filesystem, etc.).

Cross-project tests

Some tests span projects (integration, contract). Options:

Migration

Single repo → monorepo

  1. Establish tooling (Nx / Turborepo / Bazel)
  2. Migrate first 2-3 projects
  3. Validate affected-only works
  4. Migrate remaining
  5. Set CI to affected-only for merges to main

Expect 3-6 months for large repos.

How SUSA fits

SUSA can run per-app exploration in a monorepo. Each app / web-domain gets its own exploration target. Affected logic can route:

Monorepo CI orchestrates SUSA alongside other tests:


jobs:
  susa-android:
    if: ${{ needs.affected.outputs.android == 'true' }}
    steps:
      - run: nx build mobile-android
      - run: susatest-agent test app.apk --persona curious --steps 100

Scaling checklist

Monorepos scale testing well when managed. Wrong setup makes them worse than separate repos. Invest in tooling.

Test Your App Autonomously

Upload your APK or URL. SUSA explores like 10 real users — finds bugs, accessibility violations, and security issues. No scripts.

Try SUSA Free