Ler original em português

← All Contents

dooopSoftware · Quality · 12 min

How to Safely Test AI-Generated Code

AI-generated tests help, but are not enough: approve code only after verifying behavior, risks, and real effects in the environment.

Published on September 6, 2026

CORE THESIS

Tests generated by the same AI may only confirm the convenient path.

Approval requires observed behavior, negative cases, and independent verification.

When the same artificial intelligence generates the code and suggests the tests, the team needs to verify more than just the appearance of the suite. Testing AI-generated code requires separating three pieces of evidence: the code compiles, the tests seem coherent, and the observed behavior meets what the product needs to deliver. AI-generated tests can help but should not become the sole proof. Before acceptance, independent verification of behavior is necessary.

Why AI-Generated Tests Need Independent Verification

When the same AI generates the solution and suggests the tests, there is a risk to consider: the tests may confirm the way the solution was conceived. This does not mean they are wrong. It only means they may be too close to the implementation.

The problem is not using AI-generated tests. The problem is accepting these tests as if they alone prove that the change solved the right problem.

A test is an artifact. Quality evidence is something else. The evidence needs to show that an input, an action, and an expected state were observed under conditions relevant to the product. If the test only exercises an isolated function, with convenient data and without verifying real effect, it may be useful to locate technical errors but remains weak for approving behavior.

Test coverage also needs to be treated carefully. It can indicate which parts of the code were executed but does not confirm that relevant scenarios were chosen, that user criteria were met, or that dangerous failures were blocked. Coverage helps investigation. It does not replace judgment.

This distinction becomes more relevant when the team adopts code generation tools at scale. Leadership does not need to block AI. It needs to prevent production speed from becoming acceptance speed. The quality process must continue asking: what behavior was promised, what behavior was observed, and what risk remains unverified?

This discussion connects to the broader topic of business-connected artificial intelligence strategy. If AI enters development without decision criteria, it amplifies both delivery capacity and the capacity to produce false confidence.

Define Expected Behavior Before Reviewing the Generated Suite

Before reading the generated tests, describe the expected behavior of the change. This description does not need to become a long document. It needs to be verifiable.

A good behavior criterion answers at least:

  • What input or condition initiates the change?
  • What action should the system perform?
  • What result needs to be perceived by the user, another system, or an internal routine?
  • What state must be persisted, changed, or preserved?
  • What side effect is acceptable?
  • What situation should block the action?

This order matters. If the team starts with the generated tests, they tend to evaluate whether they "make sense." If they start with behavior, they evaluate whether the tests prove something relevant.

Imagine a fictional scenario: a team asks an AI to change the discount rule of an e-commerce. The generated code applies a promotional coupon. The AI also creates tests to validate an active coupon and calculate the final price. Everything passes.

Still, the quality question is not answered. The expected behavior might include rejecting expired coupons, preventing duplicate use, blocking discounts for ineligible customers, and recording the reason for refusal for support. If these criteria were not written before approval, the suite that "passes" may only be confirming the happy path.

Leadership should request a verifiable sentence, not an abstract justification. For example: "Given an expired coupon, when the customer tries to apply it in the cart, the system must refuse the discount, keep the original value, and record the reason for refusal." This sentence already guides automated testing, manual exploration, and review of effects in the environment.

Cross-Check Existing Tests, Generated Tests, and Risk Gaps

After defining behavior, the suite can be read in three layers.

The first layer is existing tests. They indicate which behaviors the team already considered relevant before the change. The question here is simple: was something that was already protected removed, relaxed, or bypassed to make the new code pass?

The second layer is AI-generated tests. They may reveal scenarios the team had not remembered, automate repetitive checks, and speed up writing simple cases. But they must be evaluated as proposals, not as authority. The generated test needs to be read with the same productive skepticism applied to the generated code.

The third layer is risk cases. These are situations where an error would have a greater impact, even if the case is less frequent. Not every risk deserves immediate automation. Some deserve manual review, exploratory testing, integration simulation, or gradual release.

The comparison should produce an objective question: what behavior remains unproven?

This question avoids two extremes. On one side, approving because "there is a test." On the other, rejecting everything generated by AI on principle. The point is more mature: identify evidence gaps and decide how to address them.

DORA recommends testing throughout development, combining automation with manual activities such as exploration and usability, as well as maintaining and reviewing test suites. This reference supports an important practice: quality is not a later stage to stamp what has already been done. It is a set of checks distributed during the change.

Include Negative and Edge Cases in the Review

Even when the main path seems clear, the review of AI-generated code should include edges such as permissions, old states, incomplete data, invalid inputs, concurrency, unavailable integrations, and rules that only appear when the product encounters real operation.

Negative cases are situations where the system should not produce the happy result. They test refusal, limits, interruption, or state preservation. In many products, the most costly error is not failing to do something. It is doing something that should not be done.

Returning to the fictional discount coupon example, the generated tests cover the valid coupon. The quality review should ask:

  • What happens with an expired coupon?
  • Does the system prevent duplicate use?
  • Does an ineligible customer receive an undue discount?
  • Is the original value preserved when the application fails?
  • Is the reason for refusal available for support or internal product audit?
  • Does a rule change affect already closed orders?

These questions do not assert that the error will occur. They delimit failure hypotheses that need to be verified according to risk.

A practical criterion: for each AI-generated change, require at least one case proving the happy path and at least one case proving a relevant refusal. In features critical to revenue, permission, privacy, availability, or core user experience, this minimum tends to be insufficient but already prevents approval based only on the convenient scenario.

Here is an important difference compared to business-connected artificial intelligence strategy. The strategy defines adoption, governance, and priority criteria. Testing behavior asks whether the system does what it should do under observable conditions. The two practices complement each other but one does not replace the other.

Verify Effects in the Environment, Not Just Success Messages

A test that receives "success" as a response may still not prove the real result. The change may have returned the correct message but not recorded the expected state. It may have updated the database but not published an event. It may have called a simulated integration but left a queue in an inconsistent state. It may have logged an entry but with improper permission.

Anthropic, when discussing agent evaluations, distinguishes the execution trajectory from the effective result in the environment: a message saying the task finished is not enough to prove the result. The evaluation uses inputs, success criteria, and verifiers, and may require multiple attempts, as described by Anthropic.

By analogy, this distinction can guide the review of AI-generated code, even when there is no autonomous agent in production. What matters is separating "the code executed a path" from "the environment reached the correct state."

In practical terms, the team should define verifiers compatible with the expected behavior. Depending on the change, this may include:

  • database record;
  • event published to a queue;
  • file created or preserved;
  • permission correctly applied;
  • call to an external service simulated with a known contract;
  • previous state maintained when the operation fails;
  • sufficient logging for investigation without exposing improper data.

It is not necessary to turn every pull request into a heavy evaluation. The intensity of verification should match the error impact, change reversibility, and ease of observing failures after release.

A warning sign: tests that only verify a function was called without confirming the effect that justified the call. This type of test may be acceptable in low-risk internal parts but is weak when expected behavior depends on persisted state or interaction with other systems.

Choose Verification by Type of Risk

Not every verification should be automated immediately. Automation makes sense when the flow is repeatable, the success criterion is clear, and regression would be relevant. Manual exploration helps when the change involves usability ambiguity, new behavior combinations, or doubts that do not yet fit well into automated tests.

The question is not which practice seems more modern. It is which verification can observe the risk introduced by the change.

Use automation when:

  • behavior is stable and recurring;
  • error would be relevant in future regressions;
  • scenario can be reproduced with controlled data;
  • verifier can observe the result, not just execution.

Use manual exploration when:

  • experience depends on human judgment;
  • there is ambiguity in the product rule;
  • the team is still discovering which failures matter;
  • automation would create false precision.

Consider gradual release when risk depends on controlled real use, when the change is reversible, and when there are observable signals to stop exposure. The Google SRE chapter on canarying covers evaluating a change on a portion of traffic before expanding exposure. It also distinguishes making code available from activating features, using configurations to separate these decisions.

This separation is valuable for AI-generated code. Merging does not need to mean activating for everyone. The team can make the code available, keep a configuration flag off, observe in a controlled environment, and expand only if defined signals are acceptable.

METR, in its February 2026 update, considers its new data an unreliable signal of AI's current effect on productivity and points out difficulties such as participant and task selection and measuring time with competing agents, according to METR. To decide how to test the code, a prudent reading is not to use generic productivity expectations as justification to reduce quality evidence.

If the organization is building an AI roadmap, this point should appear as an engineering capability, not just as tool adoption. Better testing is part of adoption. Not an external brake on it.

Approval Checklist for AI-Generated Code

Use this checklist to avoid accepting AI-generated tests as sole proof. It does not replace the team's technical judgment but helps turn the discussion into observable criteria.

Expected Behavior

Does the change have observable criteria before reading the generated tests?

Accept when there is a verifiable description of input, action, result, and acceptable side effect.

Minimum Independence

Is there at least one verification not just suggested by the same flow that generated the code?

Accept when a human, existing test, acceptance case, or external verifier confirms relevant behavior.

Happy Path

Has the main user case been tested from the product perspective, not just the altered function?

Accept when the test demonstrates the result perceived by the user or consuming system.

Negative Cases

Does the suite prove the system refuses, limits, or interrupts invalid situations?

Accept when there is coverage for at least one predictable error, improper permission, or out-of-pattern input.

Regression

Does the change preserve behaviors that already existed and should not change?

Accept when relevant existing tests continue passing and the team reviews if any test was removed, relaxed, or bypassed.

Real Effect

Does the test verify the state produced in the environment, not just a success message?

Accept when database, queue, file, event, permission, or persisted state are checked whenever part of expected behavior.

Release

Does the residual risk allow direct merge, manual exploration, configuration flag, or gradual exposure?

Accept when the release decision is linked to error impact, reversibility, and ability to observe failures.

Approval rule: no AI-generated code should be accepted solely with tests generated by the same AI. It can be an existing test, a negative case written by the team, guided manual exploration, or gradual release with defined signals. What should not pass is automatic approval of a package where AI wrote the code, wrote the tests, and also alone defined what counts as quality.

If your team is reviewing how to adopt AI with more engineering and product criteria, consider talking to dooop.

Further Reading

Sources

NEXT STEP

Discuss Application in Your Company

Conversation about the software company context

Content by dooop. Registration allows linking this topic to the reader's journey and tracking interest in the subject.