Business

When to Accept a Live Call in Your Test Suite

Antonio Evans9 min read

A split scene showing a test suite as a pipeline with two lanes: one lane runs fast with mock icons, the other lane has a turnstile labeled 'LIVE' with a counter showing a budget of 20 calls.
Key points

Key points

  1. 1A live model call is justified only when the assertion is about the model's own behavior or a seam a mock cannot reproduce, such as auth, retries, streaming or output shape.
  2. 2The cheapest test that can catch a given bug wins: fake client first, recorded fixture second, mock server third, live call last.
  3. 3Cap live calls per test file (10 to 20 is a workable starting budget) and set a hard timeout on every call so one hung request cannot stall the pipeline.
  4. 4Gate live suites behind an environment variable or CI label so they run on a schedule and on demand, not on every commit.

Start with the question the test is allowed to answer

The single most useful testing rule for model-backed code is this: decide what question the test answers before you decide how it gets its answer. A test that checks your JSON parser should not need a live provider, a current model and a healthy rate limit to be green. The live dependency adds noise to a deterministic assertion, and a test that flakes for reasons unrelated to the code under test trains the team to rerun instead of debug, which is how expensive tests become weak tests 12.

Prompt testing as a discipline runs a prompt and its full configuration (model, temperature, tools, response format, retrieval) against representative inputs with explicit expectations, and scores each run the same way. That is a different activity from unit testing deterministic code, and Braintrust lays out the distinction clearly: prompt tests answer "does this configuration still behave correctly on the cases we care about," while unit tests answer "does this deterministic code return the expected value" and run in seconds on every commit 11. Keeping those two questions separate is the precondition for everything below.

The second precondition is knowing what each layer can and cannot prove. The same Braintrust comparison notes that prompt edits which add examples or reasoning instructions can improve accuracy while also increasing latency and token spend, so cost and latency belong in the same test run as quality, not in a separate review 11. If you are going to spend a live call, make it earn its keep by covering the expensive dimensions too.

The decision table

Four layers cover almost every case. Move down the list only when the layer above cannot produce the signal you need.

Question your test asksLayerWhat it provesWhat it costsFlakiness risk
Did my prompt builder, parser, retry logic, router or UI state behave correctly?Fake client or handwritten doubleYour application logicMilliseconds, zero spendNear zero
Does my code still handle the real request and response wire shape?Record and replay fixtureCompatibility with a captured exchangeOne recorded call, replayed freeLow
Does my app survive streaming, latency, malformed JSON, 429s and provider errors?Mock server or simulatorWire-level resilience and error handlingZero spendControlled
Did the model still produce acceptable output on important cases?Live call or live eval suiteOutput quality against explicit criteriaReal tokens, real quotaReal

The layer descriptions mirror the LLM testing decision table published by Agiflow, which maps each question to a layer and states what that layer does not prove: a record and replay fixture proves compatibility with a captured exchange, not whether today's model behavior is good 12. A mock server covers error handling but tells you nothing about real provider performance.

The cutoff rule I use is a single sentence: accept a live call only when the assertion cannot be written without the model's actual output. In practice that means three families of test qualify. First, output contract tests where the model's response shape is the thing under test (valid JSON against a schema, required fields present, refusal behavior on disallowed inputs). Second, prompt change tests where you need to observe the effect of an edit on response shape or content. Third, integration seam tests where the live path is the point: auth headers, retry ceilings, streaming chunks arriving in order, timeout handling on a slow provider.

The general mocking-versus-live literature agrees on the shape of the split even where it is not about models. Sparrow's integration testing guidance recommends mocks for fast feedback during development, for backends that are not ready and for error and edge conditions that are hard to trigger against a live API, and live calls for validating the real contract and gaining pre-release confidence 18. Zuplo makes the same point about quota and availability: hit live only when you must, because you are betting on a third party's uptime and your own spend 17. Stack Overflow's long-running integration test debate lands in the same place from the other direction: mock the external parts, or the test stops being a meaningful integration of anything 16.

A useful habit is to write the assertion first, with no call in it, and ask whether it can pass or fail meaningfully. If the answer is "only if the model returns something," you have justified a live call. If the answer is "only if my code does the right thing with whatever comes back," you have justified a fake.

Worked example: what a live call actually costs

Take a small suite with 12 live tests, each making one call with a 2,000-token prompt and a 500-token response. That is 24,000 input tokens and 6,000 output tokens per run. Run it on every push across five engineers pushing several times a day and the token count grows quietly but steadily, while the failure noise grows faster: a single provider hiccup can red the build.

Now apply the decision table. Of those 12 tests, maybe three genuinely assert model output (schema compliance, refusal behavior, one prompt regression case) and two assert an integration seam (streaming order, retry ceiling). The remaining seven are parser, router and error-mapping tests that can run against fakes and recorded fixtures in milliseconds. The live budget drops from 12 calls to 5, and the seven cheap tests go back to running on every commit where they belong.

The numbers are illustrative, but the framework behind them is published. OpenAI documents rate limits across metrics such as requests per minute, tokens per minute and requests per day, with work throttled by whichever limit is hit first, and recommends separate staging and production projects so development and testing traffic can be isolated with their own rate and spend limits 12. That recommendation is the structural version of the budget: a dedicated test project means a runaway suite cannot touch production quota. The same source notes that prompt caching can reduce latency and input token cost when repeated prefixes qualify, which matters for suites that reuse a long system prompt across many live tests 12.

The practical budget rule: start with 10 to 20 live calls per test file and treat that cap as a test of its own. If a file needs more, the extra tests are usually asserting something a fixture could assert.

Rate-limit live calls so they never take down the quota

Rate limiting is a control plane, not a guardrail. The basic components are the limit (maximum allowed requests), the time window over which it applies, and the identifier that distinguishes one client from another; when a client exceeds its allocation, requests are rejected with HTTP 429 and headers that say when the limit resets 19.

For a test suite, the identifier is you, or more precisely your test project. Three practices keep the suite inside the ceiling.

  1. Serialize live tests inside a file and cap concurrency across files with a semaphore or a test-runner flag. A dozen parallel workers each firing live calls will hit the same limit and produce failures that look like regressions.
  2. Treat 429 as a signal to back off and retry with jitter, and assert that behavior in a mock-server test so you know the retry path works before you meet a real limit. Zuplo's mocking guide points out that triggering a consistent 429 against a live API is nearly impossible, which is exactly why the mock belongs in the suite 17.
  3. Pause between calls using the reset headers the provider returns rather than a guessed interval, and set a hard per-call timeout so a stalled connection does not consume the entire test job's wall clock.

The Stack Overflow question about YouTube's quota on unit tests shows the same failure mode in plain terms: repeated live calls burn a per-endpoint quota, and the advice is to mock only the endpoints you actually use rather than the whole API 20. You do not need to run the real provider to know that your client honors a rate limit.

Gate live suites behind flags and a schedule

The gate is the part teams skip, and it is the cheapest to implement. Live tests should be off by default and on in three situations: a scheduled run, a pull request labeled for it, and a manual dispatch.

# pytest: skip live tests unless the flag is set
LIVE_MODEL_TESTS=1 pytest tests/ -m live

# gate in CI: only the scheduled job and labeled PRs export the flag
if [[ "$EVENT_NAME" == "schedule" ]] || [[ "$PR_LABELS" == *"live-model"* ]]; then
  export LIVE_MODEL_TESTS=1
fi

The reason to gate rather than to rely on discipline is that prompt configuration changes behave like code changes but often skip the safeguards code gets. Langfuse's prompt CI/CD guidance makes the point directly: a prompt edit changes production behavior the same way a code change does, but in most teams it skips every safeguard code changes routinely pass 14. The gate is what puts the safeguard back without putting live calls on every commit.

Labeling a pull request is the right ergonomics because the person changing the prompt is the person who should select the live run. A scheduled nightly run catches drift and provider-side changes without blocking anyone. Everything else runs against fakes and fixtures.

Operational limits should live in the same run as quality. The Braintrust comparison places latency and token cost alongside correctness and format compliance precisely because prompt edits can trade one for the other 11. If your live suite records duration and token counts per test, you get the cost conversation for free every time it runs.

Collect evidence when a live test fails

A live failure that says "expected 'approved', got 'review'" is useless to a reviewer who cannot see the inputs. Attach the evidence to the work item: the prompt version, the model and parameters, the request and response, the scorer output and the artifact path. Agiflow's task evidence model lists fixture diffs, the reason a cassette was refreshed, the eval command, the threshold, the source link and the artifact path as the things that let a human or an agent prove what changed 12.

Recording the full configuration next to each prompt version is what makes two runs comparable. When the score drops between runs, you can trace it to a model swap or a temperature change as readily as to an edited instruction, which is the whole point of storing configuration with the prompt 11. Without it, a live failure is a shrug.

The same discipline applies to prompt versioning. Langfuse's regression testing material frames the goal as catching the prompt tweak that fixes one complaint and quietly breaks ten other answers before it ships 13. That is a live-eval job, and it is why the live suite exists at all: not to test your parser, but to catch the change nobody expected to matter.

If your team is wiring this into a real product and wants one key for text, image, audio and embedding models with OpenAI-compatible calls and prepaid US dollar pricing, that is what Quanta Inference is for, and a separate test project under that key keeps live suites off your production quota.

A checklist before you merge the live test

  • The assertion cannot be rewritten against a fake or fixture without losing meaning.
  • The test has a hard timeout and, if it retries, a documented retry ceiling that is itself covered by a mock-server test.
  • The call is counted against a per-file budget of roughly 10 to 20 and a total run budget.
  • The suite is gated: off by default, on for scheduled runs, on for the labeled pull request, on for manual dispatch.
  • The failure artifact includes prompt version, model, parameters, request and response, and the scorer result.
  • The live call runs against a dedicated test project, not the credentials your production service uses.

The hardest item is the first. It is also the only one that decides whether the test is worth its cost. If you cannot articulate the behavior the live call proves, the fixture already covers it.

FAQ

FAQ

When exactly should a test call the real model?

When and only when the assertion is about the model's own output or a seam a mock cannot reproduce: the response contract, the effect of a prompt edit on response shape, or integration behavior such as auth, retries, streaming order or timeout handling. Everything else belongs in a fake client, a recorded fixture or a mock server.

How many live calls should a test file make?

Start with 10 to 20 per test file and treat that as a cap you have to justify crossing. A file that needs more is usually asserting something a fixture could assert, and the extra calls add flakiness along with cost.

How do I stop live tests from hitting rate limits?

Serialize live tests, limit cross-file concurrency, honor the provider's reset headers instead of guessing intervals, and set a hard timeout per call. Run the suite against a dedicated test project with its own quota so it cannot touch production limits.

Should live tests run on every pull request?

No. Gate them behind an environment variable or a CI label so they run on a schedule, on demand and on the pull request that actually changes a prompt or an integration seam. Live calls on every commit turn provider noise into build noise.

What should a live test log when it fails?

The prompt version, model and parameters, the full request and response, the scorer output and the artifact path. Storing configuration with the prompt version is what lets you trace a score drop to a model swap or a temperature change instead of guessing.

If you are deciding how much of your evaluation work can be moved off live calls and want a second opinion on the split, a free 30-minute discovery call with Quanta Consulting is a reasonable place to take your current suite and talk through the budget.

Sources

Sources

  1. Mock LLM Responses Without Hiding Real AI Failures in CI
  2. What is prompt testing? Test cases, datasets, and regression ...
  3. When to Mock vs. When to Hit Live APIs: Integration Testing Best ...
  4. How to Implement Mock APIs for API Testing - Zuplo
  5. Is it in considered a good practice to mock in integration test? closed
  6. API Rate Limiting at Scale: Patterns, Failures, and Control ...
  7. How to handle API call rate limit when unit testing?
  8. Prompt CI/CD: version, gate, and roll out prompts like code
  9. LLM regression testing: fail CI before regressions ship
About the author

About the author

Antonio Evans
Antonio Evans

Antonio Evans is the founder of Quanta Intelligence and a fractional CTO who builds HIPAA-ready AI systems for health and life-science companies. Before that he was technical co-founder of FriendsEAT for twenty years, CEO of Socialdraft, and a data engineer at IBM. Antonio lives with his dog Santino in Lisbon, Portugal.

All articles