BXUP Track progress & test yourself — free
QA & Testing · Playbook · Advanced · ~5 min read
QA & TESTING · PLAYBOOK · ADVANCED

Optimize a Regression Suite with Embeddings

Regression suites grow by accretion — every incident adds tests, none retire — until runtime, not risk, decides what gets tested. Embeddings make suite overlap measurable: semantically near-duplicate tests cluster together, tests map to features for change-based selection, and cuts happen against an explicit risk budget instead of a hunch.

Tier: Advanced · Workflow area: Triage, flakes & defect intelligence

This playbook embeds your test corpus, finds redundancy candidates and coverage gaps, builds a test-to-feature map for change-based selection, and retires tests through a coverage-guarded process — never on similarity score alone.

USE IT WHEN

Scale has outrun judgment

  • The regression suite runs 2+ hours and nobody can say which tests earn their runtime.
  • Years of copy-paste authoring (and lately, AI generation) have bred near-duplicates no grep can find.
  • You want change-based selection — run what the diff touches — but no test-to-feature map exists.
SKIP IT WHEN

The suite is small or the signal is elsewhere

  • Under ~300 tests: an afternoon of human review beats the pipeline.
  • Runtime pain is really flake-retry pain — fix flakes first; a fast lying suite is worse than a slow honest one.
  • Code-coverage-based selection already works well in your mono-language repo — embeddings add semantics, but coverage traces may already suffice.

Prerequisites

  • The suite exportable as text units: test name, file, body (and docstring/description) per test.
  • An embeddings API (OpenAI text-embedding-3-small, Voyage, or local via Ollama) and a few lines of Python — no vector database required at this scale.
  • Code coverage per test (pytest-cov, Istanbul/nyc per-spec) for the retirement guard.
  • A feature/component inventory — even a rough one from your repo's module structure.

The workflow

  1. Extract test units. One record per test: identifier, source text, file path, tags, runtime, last-5-runs status. A 50-line script over your test tree; keep it in the repo — you will rerun this quarterly.

  2. Embed and cluster.

    # embed_suite.py — sketch
    embs = client.embeddings.create(model="text-embedding-3-small",
                                    input=[t["text"] for t in tests])
    # cosine similarity matrix; pairs above 0.90 -> duplicate candidates
    # agglomerative clustering at 0.80 -> semantic groups per feature area
    

    Output two artifacts: a ranked list of high-similarity pairs (duplicate candidates) and cluster membership (the raw material for the feature map).

  3. Review duplicate candidates with an assistant — semantically, not numerically. Similarity flags candidates; a language model plus a human decide:

    These two tests scored 0.94 cosine similarity (sources attached).
    Answer: (a) do they exercise the same behavior path, or same setup with
    DIFFERENT assertions? (b) what does each catch that the other would miss?
    (c) verdict: TRUE-DUPLICATE / OVERLAPPING-KEEP-BOTH / DISTINCT.
    Quote the assertion lines that justify the verdict.
    

    Expect the humbling case: 0.94 similarity, but one asserts the happy total and the other asserts the rounding edge — keep both. Verdicts are drafted by the model, confirmed by a reviewer who reads the quoted assertions.

  4. Guard every retirement with coverage evidence. A test dies only if the survivors cover its ground:

    pytest --cov=src --cov-report=json tests/keep_set/     # coverage without the candidate
    python scripts/coverage_diff.py candidate=tests/checkout/test_totals_v2.py
    # -> "0 lines uniquely covered by candidate" = safe; anything else = keep or port asserts
    

    Retire in a dedicated PR listing each test, its duplicate-verdict, and its coverage-diff result. Mutation-test the survivor set on affected areas if you want the stronger guarantee that assertion power, not just line coverage, survived the cut.

  5. Build the test-to-feature map for change-based selection. Embed feature descriptions (or module READMEs/paths) in the same space and assign each test cluster to its nearest features. Store the map as data:

    { "tests/checkout/test_totals.py::test_vat_rounding":
        ["pricing-engine", "checkout-flow"] }
    

    Wire selection into CI: diff touches src/pricing/** → run mapped clusters plus the always-on smoke tier. Uncovered-by-map diffs run the full suite — the map must fail safe.

  6. Find the inverse signal: gaps. Clusters of app features with zero mapped tests, and incident postmortems whose embedded descriptions land far from every test cluster, are your coverage holes — feed them to the test-design playbooks. The same matrix that finds redundancy finds absence.

  7. Set the risk budget explicitly and re-run quarterly. Decide, in writing, the target: e.g. "PR gate ≤15 min at ≥95% historical-defect recall; nightly runs everything." Validate selection against history — replay the last quarter's defect-introducing commits and confirm the selected subset would have caught them. Re-embed as the suite and app evolve.

Key Takeaway:

Embeddings measure semantic distance, not importance. They are superb at surfacing candidates — duplicates, mappings, gaps — and blind to why a strange-looking test exists (that regression test for the 2023 Diwali-sale incident looks like an outlier and is untouchable). Coverage diffs, defect-history replay, and a human verdict stand between similarity scores and the delete key.

Variations

  • Local-only pipeline: Ollama embedding models keep test source in-house — quality is adequate because test code is short and structured; thresholds may need retuning.
  • Coverage-trace hybrid: intersect embedding-based selection with per-test coverage traces; the union catches both semantic relevance and mechanical reachability, the intersection is your highest-confidence fast tier.
  • Runtime-weighted cuts: rank duplicate candidates by runtime saved × flake rate — retire the slow flaky twin, keep the fast stable one.
  • Vendor selection tools: predictive-selection products do this with proprietary models; run this pipeline first anyway — the scorecard question "beat my embedding baseline" is a strong POC filter.

Quality check

  • No score-only deletions: every retired test has a model verdict with quoted assertions plus a clean coverage diff, reviewed by a human.
  • Recall validated: change-based selection replayed against ≥1 quarter of real defect-introducing commits; recall meets the written budget.
  • Fail-safe selection: unmapped diffs demonstrably trigger the full suite (test this path deliberately).
  • Runtime target met: PR-gate wall-clock at or under budget, with the numbers before/after in the PR that shipped the change.
  • Gap list actioned: identified coverage holes turned into test-design tickets, not just an interesting chart.

Pitfalls

  • Deleting the outlier that is actually the crown jewel. Incident-born regression tests are semantically weird by nature. Tag incident/regression tests as unretirable before the pipeline runs.
  • Embedding names instead of bodies. Test names lie ("test_edge_case_2"); embed the body and assertions or the clusters are fiction.
  • Same-setup-different-assert merges. The 0.9+ pair that differs only in its final expect is the classic false duplicate — this is why step 3 demands quoted assertion lines.
  • A stale map silently under-selecting. New features ship, map unchanged, PR gate green because nothing relevant ran. Re-embed on a schedule and alert on unmapped-diff rates.
  • Optimizing a flaky suite. Flake noise poisons last-5-runs data and wastes the whole exercise; stabilize first.

Restricted-environment variant

Test source often embeds client business logic in its scenario names and data. For client-owned suites, use client-approved embedding endpoints or run local embedding models; never ship the corpus to a personal account. The artifacts this playbook produces — duplicate ledger, feature map, risk-budget document — are exactly what client audits ask for when you propose cutting their regression suite: keep them in the engagement's document store, with the coverage diffs attached to every retirement PR.

Success criteria

  • Suite runtime (or PR-gate tier) cut by a defensible margin — typically 30–50% — with the risk budget document showing what was traded.
  • Zero escaped defects attributable to a retired test or under-selection in the following quarter.
  • A versioned test-to-feature map driving change-based selection in CI, with fail-safe full runs on unmapped changes.
  • Quarterly re-embedding scheduled and owned — optimization as a practice, not a purge.
Pro Tip

Publish the duplicate ledger internally before deleting anything. Authors defending "their" flagged tests will hand you exactly the missing context — the incident it guards, the subtle assert difference — that no similarity score contains. The argument is the review.

This is the free reading view. Open BXUP to track your progress, run the hands-on labs, and prove it with original, exam-pattern assessments.
© Anvi Innovate · BXUP — Be Exponentially Upskilled · BXUP is an independent learning platform, not affiliated with or endorsed by AWS, Microsoft, Google, NVIDIA, IBM, Salesforce, Databricks, Oracle or Anthropic. All trademarks belong to their respective owners. · bxup.in