Skip to main content

How to use TDD with AI to save money

Test-Driven Development (TDD) is already a proven method to improve code quality and maintainability. But what if you could also use TDD to reduce your AI usage costs? Spoiler: You can. By leveraging unit tests and integration tests, you can teach the AI more efficiently and reduce the number of prompts it requires.

Here’s how.

Why TDD saves money when using AI

When you work with AI agents like Cline or Claude 3.5, you’re charged for every token you send and receive. Each prompt costs money, and every response from the AI eats into your budget. However, when you incorporate TDD, you provide the AI with a clear framework to follow. Instead of explaining every tiny detail, you let your tests do the talking.

AI can read your tests

One of the coolest things about AI is that it can read and understand your codebase, including your tests. By writing comprehensive unit and integration tests, you give the AI a way to infer what your code should do without needing you to explain it repeatedly.

Example:

// Unit test
describe('add', () => {
    it('should return the sum of two numbers', () => {
        expect(add(1, 2)).toBe(3);
    });
});

Instead of saying, “Make sure the add function returns the sum of two numbers”, you simply ask the AI to ensure the function passes all tests. This drastically reduces your input tokens.

Sample prompt to AI:

"Fix the add function so that it passes all the unit tests."

Sample output from the AI:

function add(a, b) {
    return a + b;
}

The AI understands the requirements from the test and provides a correct implementation without needing a long explanation.

Unit tests: your cost-saving friend

Unit tests cover individual functions or components. They are small, fast, and easy to write. Here’s why they’re critical for saving money:

  • AI can use them as a reference: If the AI knows that your function must pass a set of tests, it will optimize the code accordingly.
  • Less back-and-forth: Instead of repeatedly correcting the AI’s output, you can point it to the tests and say, “Make it pass these”.

Example prompt:

"Fix the add function to pass all tests."

This is much cheaper than explaining each requirement separately.

Example scenario

Let’s say you have a buggy function:

function add(a, b) {
    return a - b;
}

Without tests, you’d need to tell the AI what’s wrong. With tests, you just say:

“Make it pass the existing unit tests.”

Sample output from the AI:

function add(a, b) {
    return a + b;
}

Integration tests: handling complex scenarios

Integration tests ensure that different parts of your application work together as expected. These tests cover more complex use cases and are particularly useful when working with APIs or databases.

For example:

// Integration test
describe('User Service', () => {
    it('should create a new user and fetch it from the database', async () => {
        const user = await userService.createUser({ name: 'Alice' });
        const fetchedUser = await userService.getUser(user.id);
        expect(fetchedUser.name).toBe('Alice');
    });
});

Sample prompt to AI:

"Ensure the userService passes all integration tests."

Sample output from the AI:

async function createUser(userData) {
    const newUser = await database.insert(userData);
    return newUser;
}

async function getUser(userId) {
    const user = await database.findById(userId);
    return user;
}

With a test like this in place, you don’t need to describe the entire flow to the AI. The AI reads the test and fixes the implementation accordingly.

AI-driven development with tests

Here’s how you can integrate TDD into your AI workflow:

  1. Write tests first: Start by writing unit and integration tests for the functionality you need.
  2. Ask the AI to implement the code: Instead of lengthy prompts, simply instruct the AI to make the code pass all the tests.
  3. Refactor using tests: When you want to optimize or refactor code, let the AI know that the code must continue to pass the existing tests.

Saving money with smarter AI usage

By using tests as a guide for the AI, you reduce the need for detailed prompts and back-and-forth interactions. This leads to:

  • Fewer tokens consumed: Shorter, more concise prompts mean fewer input tokens.
  • Less verbose responses: The AI doesn’t need to over-explain when it has clear tests to reference.
  • Higher accuracy: The AI delivers better results because it has a concrete set of rules to follow.

Real-world example: debugging with TDD

Imagine you have a buggy piece of code that calculates discounts:

function calculateDiscount(price, discount) {
    return price * discount;
}

Your unit test looks like this:

describe('calculateDiscount', () => {
    it('should return the correct discounted price', () => {
        expect(calculateDiscount(100, 0.2)).toBe(80);
    });
});

Sample prompt to AI:

"Fix calculateDiscount so it passes the tests."

Sample output from the AI:

function calculateDiscount(price, discount) {
    return price - (price * discount);
}

Conclusion

Using TDD with AI isn’t just good for your codebase — it’s good for your wallet. By writing comprehensive unit and integration tests, you can reduce your AI usage costs, streamline your workflow, and get better results with fewer prompts.

In the end, letting your tests do the talking is a smarter, more efficient way to collaborate with AI. And let’s be honest — who doesn’t want to save money while coding?