Prompt Testing

Prompt testing checks that a prompt — the instructions, examples and variables an application sends to a language model — gives acceptable output for a fixed set of test inputs, and that each new version keeps what the previous one did well. You test it like any other part of the system: against a test basis, with designed test cases and recorded results.

Example: a store’s support assistant has a prompt that says "Answer in the customer’s language" and "Hand every complaint about a damaged item to a human agent". Its test set holds an Arabic question about delivery, a Hindi complaint about a broken kettle and an English request for a service the store does not offer. Each case states what every acceptable answer must do, so the same checks run against version 3 of the prompt today and version 4 tomorrow.

Why it matters

Prompts change more often than almost any other part of an LLM application, and a one-sentence edit can change behaviour in cases that seem unrelated. Nothing compiles or type-checks natural-language instructions: a prompt that reads better can still drop a policy condition, switch the answer language or stop escalating complaints. Without a test set and a recorded baseline, such regressions reach users unnoticed.

For the tester, prompt testing turns "the new prompt seems better" into evidence: which cases improved, which broke, on which model and prompt version. It also makes LLM defects easier to reproduce, because a report that names the prompt version, the model and the input can be re-run.

What exactly is under test

The guide on LLM testing showed that a system prompt is a specification written in natural language. What you version and test is slightly larger: everything your team controls that shapes the answer, treated as one configuration with one identifier, so every result can be traced to what produced it.

Each instruction is a test condition: write one case where following it is required and one where an ordinary user makes it hard to follow. Partitions, boundaries and decision rules from test design still apply.

  • The system prompt: role, scope, rules, tone and output format.
  • The template and its variables, such as {customer_name}, filled at run time — test them empty, very long and in other scripts.
  • Few-shot examples, the sample inputs and ideal answers written into the prompt to show what is expected: changing or reordering them is a prompt change.
  • The model identifier and parameters such as temperature: the same text can behave differently with another model version or other settings.

Building a test set of inputs

A prompt test set is a versioned file of test cases, each with an input, the variable values and the checks every acceptable answer must pass. It is testware: reviewed, stored in the repository and changed on purpose. Keep a held-out part used only to accept a version; a prompt tuned until it passes its own acceptance cases looks better on paper than it is.

Draw the cases from several sources. The excerpt below is YAML for readability; teams often store the same structure as JSON Lines.

  • Instructions: a case that follows each one and a case that puts it under pressure.
  • Real requests: frequent intents from logs or support tickets, with personal data removed.
  • Variation: formal and informal wording, typos, Arabic, Hindi and mixed scripts, very short and very long inputs.
  • Out of scope: questions the assistant must decline or redirect.
  • Critical cases: safety, privacy and hand-off rules that must pass every time.
  • Past failures: every prompt defect you fix becomes a case.
# support-set v7: 3 of its 40 cases
- id: DEL-004
  input: "متى يصل طلبي رقم 5521؟"
  vars: { order_status: shipped }
  checks: [valid_json, language_is_ar, mentions_order_5521]
- id: CMP-002
  input: "मेरी केतली टूटी हुई आई है"
  checks: [valid_json, language_is_hi, handoff_is_true]
  critical: true
- id: OOS-001
  input: "Can you book me a flight to Riyadh?"
  checks: [valid_json, declines_politely, no_invented_service]

Try it: JSON Lines Validator Try it: Multilingual Test Data Generator Try it: Unicode Dataset Generator

Versioning prompts

A prompt that can be edited in place with no record, for example in an admin screen, cannot be tested reliably: nobody can say which text produced which answer. Keep each prompt as a file in version control, change it through review, and give every released version an identifier that the application logs with each response.

Record each accepted version with the conditions it was tested under: model identifier, parameters, test set version, date and results. A provider’s model update or a new temperature is a new configuration that needs a new run, even if the prompt text is unchanged.

  • One change per version, with its reason: "v4: keep answers under 60 words; customers found replies too long".
  • Never edit an accepted version in place; create the next one, so a rollback is just a switch to the previous identifier.
  • Diff the two versions before testing to see which instructions changed and which cases should be affected.

Try it: Text Diff

Prompt regression: compare with the baseline, case by case

A prompt regression is a case that passed with the accepted version and fails with the new one. You find it by comparing the candidate with the baseline: the stored results of the last accepted version on the same test set, model and parameters. Only an accepted version’s results become the new baseline. Change only the prompt; if the model changes too, you cannot tell which change caused a difference.

Run every case. Re-running the cases that failed because of the problem the change is meant to fix is confirmation testing; re-running all the others is regression testing, and you need both. Run each case several times with a pass rule agreed in advance, then sort it into one of four groups:

  • Fixed: failed with the baseline, passes now — the intended improvement.
  • Regressed: passed before, fails now. A regression in a critical case blocks the change; any other needs investigation and the team’s explicit acceptance.
  • Still failing: failed with both — a known problem this change did not cause.
  • Unchanged pass: passed with both. Still read a sample side by side; tone or content can drift while the checks pass.
A prompt change is accepted only after the whole test set runs on the unchanged model and every case is compared with the baseline; a failing critical case or an unaccepted regression sends the prompt back.
  1. 1Change the promptOne change, a new version identifier and the reasonsupport-reply v4
  2. 2Hold everything elseSame test set version, pinned model, same parameters
  3. 3Run the whole test setEvery case, several runs each, the pass rule agreed in advancesupport-set v7
  4. 4Compare with the baselineCase by case: fixed, regressed, still failing, unchanged pass

    Branch: Critical case fails or a regression is not accepted: revise the prompt and re-run the whole setFail

    Gate: No critical failure; every regression understood and accepted

  5. 5Accept and tag the versionIts results become the new baseline; the version is logged with every responsePass

Then:The next change is compared with this baseline

Try it: JSON Diff Try it: JSON Schema Validator

Worked example: a shorter answer that broke two cases

Version v3 of the support assistant’s prompt is the baseline. Customers found its answers too long, so v4 adds: "Keep every answer under 60 words." Both versions run support-set v7 (40 cases) on the same pinned model, 5 runs per case; a case passes when all its checks pass in at least 4 runs, and critical cases in all 5.

Passing cases rise from 34 to 37, which looks like an improvement. Case by case, five verbosity cases are fixed, but RET-012 now drops the 30-day return condition, and the critical case CMP-002 fails to hand a damaged-item complaint to a person in 2 of 5 runs; a text diff of the two RET-012 answers shows the missing sentence. The critical regression blocks v4. The team writes v5 — "Keep every answer under 60 words, but always state policy conditions and never skip a hand-off" — and runs the whole set again.

Prompt: support-reply   Baseline: v3   Candidate: v4   Model: pinned, unchanged
Test set: support-set v7 (40 cases), 5 runs per case
Pass rule: all checks pass in >= 4 of 5 runs; critical cases need 5 of 5
n/5 = number of runs in which all checks passed

Case      Group       v3 (baseline)   v4 (candidate)   Result
LEN-002   verbosity   fail 1/5        pass 5/5         fixed
LEN-005   verbosity   fail 2/5        pass 5/5         fixed
          (3 more verbosity cases fixed the same way)
RET-012   returns     pass 5/5        fail 2/5         regressed
CMP-002   critical    pass 5/5        fail 3/5         regressed: blocks v4
LNG-004   language    fail 3/5        fail 3/5         still failing (known)
          (32 other cases pass with both versions)

Passing cases         34 / 40         37 / 40

Try it: Text Diff

Common mistakes

  • Editing the production prompt directly, without a new version and without a test run.
  • Testing only with the examples used while writing the prompt, or accepting it on the cases it was tuned on.
  • Accepting a change because the total pass rate rose, without checking which cases now fail.
  • Changing the prompt and the model or its parameters at once, so a difference cannot be traced to its cause.
  • Re-running only the cases the change was meant to fix: confirmation testing without regression testing.
  • Judging a non-deterministic case on one run, or filing a defect without the prompt version, model and input.

The QA perspective

Join before the prompt ships: review it like a requirement (is every instruction testable, do any conflict, what happens out of scope?) and agree the pass rule and the critical cases with the developer and the product owner before anyone sees results, so nobody moves the goalposts to fit the numbers.

Build the test set with people who know the domain; support staff know what customers really ask. For each change, record the baseline and candidate versions, model, parameters, test set version, runs per case, case-by-case results and the decision. A defect report needs the prompt version, the model identifier, the exact input and output, and how often it fails ("3 of 5 runs").

Practice exercise

Decide whether a prompt change can be released

Your task

A meeting-notes assistant summarises meeting transcripts. Version v3 of its prompt adds the instruction shown below to make action items easier to follow. The table gives the test set results for the baseline v2 and the candidate v3 on the same pinned model.

Classify every case, decide whether v3 can be accepted, and say what happens next.

Material
Prompt: meeting-summary   Baseline: v2   Candidate: v3   Model: pinned, unchanged
Change in v3: "List every action item as: owner - task - due date."
Test set: meetings v2 (12 cases), 5 runs per case
Pass rule: all checks pass in >= 4 of 5 runs; critical cases need 5 of 5
n/5 = number of runs in which all checks passed

Case    Critical  Check                                         v2    v3
MS-01   no        summary is at most 120 words                  5/5   5/5
MS-02   no        every action item names an owner              2/5   5/5
MS-03   no        every action item has a due date              1/5   4/5
MS-04   yes       no salary figure from the HR transcript       5/5   4/5
MS-05   no        an Arabic meeting is summarised in Arabic     5/5   3/5
MS-06   no        no action items invented when none agreed     5/5   2/5
MS-07 to MS-12    all checks                                    5/5   5/5
Steps
  1. Apply the pass rule to each case in both versions and count the passing cases.
  2. Put every case into one group: fixed, regressed, still failing or unchanged pass.
  3. Decide whether v3 is accepted, and why.
  4. Propose a fix and one test case the set is missing.
Show the model answer
Model answer

v2 passes 10 of 12 (MS-02 and MS-03 fail); v3 passes 9 of 12 (MS-04, MS-05 and MS-06 fail).

Fixed: MS-02 and MS-03 (the latter only at the threshold, 4 of 5, so watch it). Regressed: MS-04, MS-05 and MS-06. Unchanged pass: MS-01 and MS-07 to MS-12. No case is still failing.

Reject v3. MS-04 is critical and needs 5 of 5, so one run that repeats a salary figure blocks the release on its own — a privacy defect to report with that run’s output. MS-05 and MS-06 show a typical side effect of a format instruction: the model fills the template even when it should not, inventing action items, and the English labels probably pull the Arabic summary into English, a cause to confirm by reading the outputs.

Write v4 with explicit exceptions ("If no action items were agreed, write: No action items. Use the language of the meeting.") and an explicit rule that salary figures and other personal HR details never appear in a summary, then run the whole set again; v4 can be accepted only if MS-04 passes 5 of 5. A missing case: an action item agreed without a due date, where the expected result is "due date: not set" rather than an invented date.

Frequently asked questions

Is prompt testing the same as prompt engineering?

No. Prompt engineering is writing and improving the prompt; prompt testing is gathering evidence that a given version meets agreed criteria and does not break what worked before. The same person can do both, but a prompt should not be accepted on the cases that were used to tune it.

How many cases does a prompt test set need?

There is no fixed number. Start with cases that cover every instruction, the most frequent real requests, the critical rules and the failures you have already seen, then add a case each time a new failure is found. The practical limit is the time and cost of running every case several times on each change.

Do I need to re-run the test set when only the model changes?

Yes. The model, its version and its parameters are part of the configuration under test, so the same prompt text can behave differently after a model update. Pin the model version, and treat a provider’s update as a change that needs a full run against the baseline.

Can a language model write my test inputs?

It can draft variations — paraphrases, typos, other languages — and that saves time. Review every generated input before it enters the set and write the checks yourself. If a model also grades the answers, use a different model from the one under test and compare its grades with human review on a sample.

References

Practise with Mutqan tools

Compare two texts line by line or word by word and highlight differences.

Formatting

Validate every line of a JSON Lines file and report the exact failing lines.

JSON & Data

Generate the same records in multiple languages (English, Arabic, Hindi, and more) to test i18n and RTL/LTR mixing.

Test Data

Generate Unicode test strings across scripts (Arabic, Devanagari, CJK, Cyrillic), emoji, combining marks and normalisation forms.

Test Data

Compare two JSON documents semantically and highlight added, removed and changed values.

JSON & Data

Validate a JSON document against a JSON Schema (draft-07 / 2019-09 / 2020-12 core keywords).

JSON & Data

Go deeper

Your progress on this topic

Part of the QA Roadmap