Enterprise Architecture →

Enterprise Software Testing When AI Writes Most of the Code

When AI generates a significant portion of the codebase, traditional testing assumptions need updating — not because testing gets easier, but because the failure modes change.

Sriram Krishnan posted recently about his personal coding arc over 20 years: from writing a lot of code every day, to writing almost none, to now generating significant amounts through LLMs — building on Andrej Karpathy’s analysis of coding models. It’s a clean description of where enterprise development is heading. More code produced per developer, with a larger share of that code originating from AI tools rather than from human hands. The follow-on question is how testing has to evolve alongside that shift.

The answer is not “test more.” It’s “test differently, in the specific areas where AI tools fail differently than humans do.”

stateDiagram-v2
direction TB
state "Assume AI output is correct" as Assume
state "Unit tests pass, boundary cases untested" as Unit
state "Integration gaps at component boundaries" as IntGap
state "Production failure or security incident" as Fail
state "Explicit interface definitions before generation" as Def
state "Boundary tests added manually post-generation" as Bound
state "Integration tests at AI-component boundaries" as Int
state "Regression protocol for AI-modified existing code" as Reg
state "Production-grade AI-assisted codebase" as Prod

[*] --> Assume
Assume --> Unit
Unit --> IntGap
IntGap --> Fail
[*] --> Def
Def --> Bound
Bound --> Int
Int --> Reg
Reg --> Prod

The assumptions that change when AI writes the code

Traditional testing is built on a model of where bugs come from. Developers make logical errors when implementing complex requirements. They misunderstand edge cases in the specification. They introduce regressions when modifying existing code. They make precision failures.

AI-generated code fails differently. It fails with confident implementation of the wrong requirement. It fails by handling specified inputs correctly and unspecified inputs incorrectly. It fails by implementing plausible-looking patterns that work in isolation and break in combination. And it fails at the boundaries — between the AI-generated component and the system it connects to — because the AI’s understanding of the surrounding system is limited to whatever was in the context window.

Testing practices designed for human failure modes catch the failures humans make. They need to be extended for the failures AI makes — which are predictable enough to address systematically.

What traditional test coverage misses in AI-generated code

Boundary and edge case coverage. Human developers often write unit tests that cover the cases they thought of while writing the code. AI tools generate code for the cases described in the prompt. Both leave the same gap: the cases nobody thought to specify. AI-generated code has this gap structurally, because the prompt defines the test scope as surely as it defines the implementation scope. If the prompt didn’t describe the edge case, the implementation likely doesn’t handle it, and the test likely doesn’t cover it.

Integration boundary testing. AI-generated components are usually developed and tested in isolation — the prompt describes the component’s behavior and the AI generates tests that verify that behavior in isolation. What the tests don’t verify is whether the component integrates correctly with the rest of the system: whether its input format matches what calling code produces, whether its output format matches what consuming code expects, whether its error behavior is compatible with the system’s error handling conventions.

Regression coverage for AI-modified existing code. When a human engineer modifies a component, they have context about what else might break. An AI tool modifying a component has only the context provided in the prompt. Regression testing for AI-assisted modifications needs to be more explicit — the AI may not know what it didn’t know to check.

What to add to an enterprise testing strategy

Three additions close most of the gap:

Explicit boundary testing. For every AI-generated function or component, the test suite should include cases for: null or empty inputs, inputs at the maximum expected size, inputs with unexpected character encoding, and inputs designed to be invalid in an adjacent system. These are the categories AI-generated code most often handles incorrectly, and they’re the categories most likely to surface in production without appearing in development.

Integration test coverage at AI component boundaries. Any interface between an AI-generated component and the existing system should have integration tests that verify the format, content, and error behavior of that interface — not just the behavior of each component independently. This is where the system-level failures accumulate.

A review gate for AI-modified existing code. When AI tools modify code that already exists — as opposed to generating new code — the diff should be reviewed specifically for regressions: which existing tests pass or fail after the change, and does the behavior change match the stated intent? This is a targeted check, not a full code review.

The Carvana case for architecture-driven testing

At Carvana — where a five-person team parsed millions of vehicle records daily through event-driven architecture — the testing strategy was architecture-driven. The event-driven pattern meant each component’s input and output were explicitly defined. The test suite verified those contracts, not just internal component behavior. When a parsing error slipped through, the event boundary testing caught it before it propagated downstream.

That architecture-driven approach maps well to AI-generated code. When each AI-generated component has an explicit interface definition — what it accepts, what it produces, what it does with malformed inputs — testing that interface is both straightforward and reliable. The AI’s implementation correctness can be verified through the interface. The AI’s edge case handling can be tested explicitly by the human who writes the test suite.

The investment in defining component interfaces before AI generation, rather than inferring them afterward, is what makes this work. It is architectural discipline applied to testing strategy, and the testing improvement is one of its secondary benefits.

The workflow that closes the gap

An enterprise testing workflow for AI-generated code:

  1. Before generation: define the component interface explicitly — inputs, outputs, error behavior, integration contracts.
  2. Generate the code and implementation tests via AI.
  3. Add boundary and edge case tests manually — the cases not described in the prompt.
  4. Run integration tests at the component boundary.
  5. For any AI-assisted modification to existing code: run regression tests and review the diff for unintended behavior changes.

Steps 3 and 5 are human steps. The AI doesn’t add them automatically. But they are predictable enough to be standardized and consistently applied — and they close the specific failure modes that AI-generated code most reliably introduces.

Frequently Asked Questions

How is AI-generated code different to test than manually-written code?

AI-generated code fails with confident implementation of the wrong requirement, rather than with the logical errors and precision failures that characterize human mistakes. It handles specified inputs correctly and unspecified inputs incorrectly. It implements plausible-looking patterns that work in isolation and break in combination. The testing gaps are predictable: boundary cases that weren't in the prompt, integration points that weren't in the AI's context, and modifications to existing code that introduced unintended regressions. Traditional unit testing isn't wrong for AI-generated code — it's just insufficient for the specific failure modes AI tools introduce.

Does AI-generated code require more testing or different testing?

Different, and in specific areas, more thorough. The highest-priority additions are: explicit boundary and edge case tests for all inputs (the cases the prompt didn't describe), integration tests at the boundary between AI-generated components and the existing system, and regression review when AI tools modify existing code. For net-new AI-generated components, the test coverage requirement is similar to manual code. For AI-assisted modifications to existing code, the regression risk is higher and requires more explicit checking.

How does defining component interfaces upfront affect AI testing?

It dramatically simplifies it. When the input format, output format, and error behavior of a component are defined explicitly before AI generation, testing that interface is straightforward — the AI's implementation can be verified against the spec, and boundary testing is explicit. When the interface is inferred from the generated code, testing is harder because the spec and the implementation are the same document. The pre-definition step also improves the quality of AI generation because the AI has a clearer target. The testing improvement is a side effect of architectural discipline that produces other benefits as well.

Shawn Livermore — Fractional CTO & Chief AI Officer
About the Author

Shawn Livermore

Fractional CTO and Chief AI Officer with nearly 3 decades of enterprise architecture experience. Clients include Kelley Blue Book, LERETA ($18B property tax processor), First American Financial, Carvana, WellPoint/Anthem, and PacifiCare. 92 client reviews, 5-star average.

View full background →

Need a fractional CTO or CAIO?

Technology leadership without the full-time headcount. Engagements start with a conversation.

Man writing a flowchart diagram on a whiteboard with a blue marker.