TDD with AI: Using Tests to Guide Intelligent Coding Agents

Overview

Software development is shifting toward agentic coding, but relying solely on AI to design your architecture often leads to a "good enough" trap. When you let an agent write both the implementation and the tests, you lose control over the developer experience and API design. Writing tests first—a classic

(TDD) approach—serves as a blueprint for the AI. It clarifies your intent, defines the desired syntax, and ensures the resulting code aligns with your personal or team standards rather than generic patterns.

Prerequisites

To follow this workflow, you should be comfortable with

and the
Laravel
framework. Familiarity with
Pest PHP
or
PHPUnit
is necessary for writing the test assertions. You also need access to an AI coding tool like
OpenCode
.

Key Libraries & Tools

  • Laravel
    : The primary PHP framework used for the application.
  • Pest PHP
    : A testing framework focused on simplicity and readability.
  • OpenCode
    : An AI-powered development platform that uses models like
    Codex
    to generate code.
  • Laravel Boost
    : A package providing specific coding guidelines and skills to the AI agent.

Code Walkthrough: Defining the API

Instead of asking the AI to "create an exporter," we write a

test that uses wishful development. This involves writing the code exactly how we want to use it before it exists.

it('exports data', function () {
    // Arrange
    User::factory()->create(['name' => 'Christoph']);

    // Act
    $csv = Exporter::export(User::class)
        ->columns([
            'name' => 'Name',
            'email' => 'Email'
        ])
        ->toCsv();

    // Assert
    expect($csv)->toContain('Name', 'Christoph');
});

In this snippet, we define a fluent interface. We decide that export() should accept a class name and columns() should take an associative array for renaming headers. By handing this test to the AI, we force it to follow our specific API design.

Syntax Notes

Notice the use of fluent methods. Each method in the Exporter class should return $this to allow chaining. The test also utilizes the Arrange-Act-Assert (AAA) pattern. This structure helps the AI understand the sequence of operations and what the final output should look like.

Tips & Gotchas

Generic prompts often result in 80% satisfaction. You might settle for naming conventions like for() when you actually prefer from(). To avoid this, never start with a blank prompt. Always provide the test file first. This prevents "code drift" where your application slowly fills with AI-generated patterns that don't match your style.

3 min read