---
name: metamorphic-testing
description: "Test systems with no reliable oracle using metamorphic relations — equivalence-preserving input transforms whose outputs must agree, with concrete relations for LLM/NLP stability. Use when: test without a correct answer oracle, write metamorphic relations, check paraphrase invariance, test llm output stability, build a metamorphic relation suite, bypass the oracle problem."
license: CC-BY-SA-4.0
metadata:
  source: "agents/skills/coding/metamorphic-testing.skill.md"
  tags: "coding, testing, metamorphic, llm, nlp"
  core: "false"
  context_cost: "medium"
---
# Metamorphic Testing

## Goal
Test systems where you cannot say what the *single correct output* is — the oracle problem.
You often can't assert "the model's answer to this question is X", but you *can* assert that
two related inputs must produce related outputs. A *metamorphic relation* (MR) is exactly that:
a transformation of the input paired with the expected relationship between the outputs. If you
reword a question without changing its meaning, a robust system should give an equivalent
answer; if it doesn't, you found a bug without ever knowing the "right" answer. This skill
produces a **metamorphic relation suite** — a set of MRs, especially for LLM/NLP stability,
where exact-match oracles are impossible. Like property-based testing, MT samples and raises
confidence; it does not prove.

## Steps
1. **Identify the oracle gap.** Confirm there is no cheap, reliable way to know the exact
   correct output (typical for ML/LLM/NLP, scientific computation, rendering, search ranking).
   If a real oracle exists, use a direct assertion or `pbt-strategy.skill` instead — MT is for
   when it does not.
2. **Derive metamorphic relations.** Each MR = an input transform + the required output
   relationship. Core families:
   - **Paraphrase / semantic-equivalence invariance**: reword the input preserving meaning →
     output should be equivalent (same classification, semantically-equivalent answer). The
     workhorse MR for LLM robustness.
   - **Noise / filler invariance**: add whitespace, harmless boilerplate, irrelevant trailing
     text, casing changes → output should be unchanged.
   - **Negation / symmetry**: negate the premise → output should flip in the defined way (a
     sentiment classifier on a negated sentence; "is A before B" vs "is B before A").
   - **Order-permutation invariance**: reorder items that should be order-independent (a set of
     facts, a list to summarize, retrieval candidates) → output should be equivalent.
   - **Monotonicity/scaling**: strengthen a signal (add more supporting evidence) → confidence
     or ranking should not move the wrong direction.
3. **Define the output-equivalence check per MR.** "Equivalent" is rarely exact-string for
   LLM/NLP. Choose the comparison: exact match (for classifiers/structured output), set or
   order-insensitive equality, or *semantic* similarity (embedding cosine above a threshold,
   or an LLM-as-judge equivalence call). State the tolerance explicitly — a too-loose check
   passes everything; too-tight flags benign variation.
4. **Distinguish hand-designed MRs from live-LLM checks.** Prefer **hand-designed MRs** with
   deterministic transforms and a fixed equivalence check — they are reproducible and cheap.
   Using a *live LLM* to generate paraphrases or to judge equivalence introduces its own
   nondeterminism and failure modes (the judge can be wrong, the paraphraser can drift meaning),
   so treat live-LLM MRs as noisier signal: pin generated paraphrases as fixtures once found,
   and cross-check judge verdicts. Never let an unvalidated LLM silently define "equivalent."
5. **Run, sample, and triage.** Apply each MR across a diverse seed set of inputs (sample — you
   cannot cover all). On a violation, the *pair* (original + transformed inputs and their
   diverging outputs) is the bug report. Triage genuine instability vs an over-tight equivalence
   check. Pin confirmed violations as regression fixtures.
6. **Compose MRs for coverage.** Different MRs catch different bugs: paraphrase invariance finds
   brittleness to wording; order-permutation finds positional bias; negation finds shallow
   pattern-matching. A single MR is narrow; assemble a suite that spans the failure modes you
   care about.

## Constraints
- MT **samples** inputs and **raises confidence**; it does **not prove** correctness. A passing
  MR suite means "no violation found in the sampled pairs under these relations" — nothing more.
- **Different MRs catch different bugs.** No single relation is sufficient; the suite's value is
  in breadth. Report which failure modes are and are not covered.
- An MR can only assert a *relationship*, never absolute correctness. A system can satisfy every
  MR and still be uniformly wrong (stable but incorrect). Say so; MT checks consistency, not truth.
- Equivalence checks for NLP are themselves fuzzy. A semantic-similarity or LLM-judge check has
  its own error rate; tune and disclose the threshold, and treat borderline diffs as inconclusive.
- Live-LLM paraphrasers/judges add nondeterminism; results from them are noisier and must be
  pinned/cross-checked, not trusted blind.

## Output Format
Produce a **metamorphic relation suite** containing:
- Each MR: the input transform, the required output relationship, and the equivalence check
  (exact / set / semantic-threshold / judge) with its tolerance.
- For each MR, whether it is hand-designed (deterministic) or live-LLM-assisted (with the
  noise caveat noted).
- The seed input set and sampling scope.
- The list of failure modes the suite covers and those it does not.
- An explicit honesty note: MT samples and raises confidence, checks consistency not truth, and
  does not prove correctness. Cross-reference `pbt-strategy.skill` for invariant-style properties
  where an oracle does exist.

## Security & Guardrails

### 1. Skill Security
- **Risk**: A passing MR suite is reported as "the model is correct/safe," when MT only shows
  consistency. Mitigation: every report MUST state MT checks relationships not truth and does not
  prove; the agent MUST NOT escalate "MRs passed" into "output is correct" — a uniformly wrong
  system passes invariance MRs.
- **Risk**: An over-loose equivalence threshold makes every MR pass vacuously, hiding real
  instability. Mitigation: the agent MUST record the chosen tolerance and justify it, and flag
  thresholds so loose that meaningfully different outputs would still be judged equivalent.

### 2. System Integration Security
- **Risk**: Running MRs (especially paraphrase generation + judging) against a live/paid model
  multiplies calls and cost, or hits rate limits. Mitigation: bound the seed set and pin generated
  paraphrases as fixtures; cap total model calls and prefer cached/deterministic transforms in CI.
- **Risk**: Metamorphic inputs that transform untrusted user text could carry injected content
  into the system under test or the judge. Mitigation: treat all transformed inputs as untrusted
  data, isolate them from any instruction context, and never let a transformed input alter test
  control flow.

### 3. LLM & Agent Guardrails
- **Risk**: A live-LLM paraphraser silently changes the input's *meaning*, so a "violation" is
  really a bad transform, not a real bug (false positive) — or a meaning-preserving paraphrase is
  judged equivalent when the output genuinely regressed (false negative). Mitigation: validate that
  transforms preserve semantics (human spot-check or a second judge), and label live-LLM MR results
  as lower-confidence requiring confirmation.
- **Risk**: The agent fabricates MRs that do not actually preserve meaning (e.g. a "paraphrase"
  that adds new constraints), producing spurious failures. Mitigation: each MR's transform MUST be
  justified as meaning-preserving (or meaning-flipping, for negation MRs) with an example pair, and
  the agent MUST mark agent-generated relations as proposed pending review.
