Using Test-Driven Development to Get Better AI-Generated…
    Neura MarketNeura Market/Cursor
    ChatGPTChatGPTClaudeClaudeGeminiGeminiCursorCursorGrokGrokPerplexityPerplexityDeepSeekDeepSeek
    CoPilotCoPilotStable DiffusionStable DiffusionMidjourneyMidjourney
    View All Directories
    OverviewRulesPromptsMCPsAgentsGamesBlogVideosGuidesCoursesCommunityExtensionsTrending
    CursorBlogUsing Test-Driven Development to Get Better AI-Generated Code
    Back to Blog
    Using Test-Driven Development to Get Better AI-Generated Code
    javascript

    Using Test-Driven Development to Get Better AI-Generated Code

    André Gardi April 18, 2025
    0 views

    This is not a vibe coding tutorial. But most developers agree that AI writes better code when you...

    image

    This is not a vibe coding tutorial. But most developers agree that AI writes better code when you give it clear instructions. Well written tests naturally include these clear details about what the code should do.

    This got me thinking — maybe test-driven development is actually a more reasonable way to use AI for coding? I decided to try it myself and see how it worked.

    TDD Basics

    You don’t need to master TDD to understand the next steps. Just understand the basic cycle: write a failing test (Red), make it pass (Green), then improve the code (Refactor). That’s enough to start.

    Environment

    We’ll write our code in JavaScript, but the principles apply to any language. We’re using Cursor AI as our editor, but other tools like Windsurf should give similar results.

    Exercise 1

    Let’s begin with a simple Fizz Buzz. I set up a minimal Node.js app with vanilla JavaScript and added Jest for testing. I wrote some tests — but intentionally avoided using the words ‘Fizz’ or ‘Buzz’ anywhere.

    const { myFunction } = require('./index');
    
    describe('myFunction', () => {
        it('should return the number itself', () => {
            const result = myFunction(49);
            expect(result).toBe(49);
        });
        it('should return pine on multiples of 3', () => {
            const result = myFunction(9);
            expect(result).toBe('pine');
        });
        it('should return apple on multiples of 5', () => {
            const result = myFunction(10);
            expect(result).toBe('apple');
        });
        it('should return pineapple on multiples of 15', () => {
            const result = myFunction(15);
            expect(result).toBe('pineapple');
        });
    });
    

    Then I gave a very simple prompt:

    On exercise-1 folder update index.js based on the tests

    The result:

    export function myFunction (num) {
      if (num % 15 === 0) return 'pineapple';
      if (num % 3 === 0) return 'pine';
      if (num % 5 === 0) return 'apple';
      return num;
    }
    

    image

    Now we can add tests for features we did not implement yet.

        it('should greet on string input', () => {
            const result = myFunction('Joe');
            expect(result).toBe('Hello Joe');
        });
        it('should return the number itself on strings that contains a number', () => {
            const result = myFunction('forty-nine');
            expect(result).toBe(49);
        });
        it('should return the number itself on strings that contains a number with space and case insensitive', () => {
            const result = myFunction('Forty nine');
            expect(result).toBe(49);
        });
        it('should return pine on strings that contains numbers multiples of 3', () => {
            const result = myFunction('Nine');
            expect(result).toBe('pine');
        });
        it('should return apple on strings that contains numbers multiples of 5', () => {
            const result = myFunction('ten');
            expect(result).toBe('apple');
        });
        it('should return pine on strings that contains numbers multiples of 15', () => {
            const result = myFunction('fifteen');
            expect(result).toBe('pineapple');
        });
    

    Again I prompted the AI to update the index.js. But the new code was converting the strings to numbers with a limited hardcoded object:

       const numberWords = {
         'one': 1, 'two': 2, 'three': 3, 'four': 4, 'five': 5,
         'six': 6, 'seven': 7, 'eight': 8, 'nine': 9, 'ten': 10,
         'eleven': 11, 'twelve': 12, 'thirteen': 13, 'fourteen': 14, 'fifteen': 15,
         'forty-nine': 49, 'forty nine': 49
       };
    

    To improve the code I asked:

    Using the numberWords object is not a good way to convert. Would a third-party lib make a better job converting the string into numbers?

    The agent installed the words-to-numbers package resulting in the following index.js:

    const wordsToNumbers = require('words-to-numbers').wordsToNumbers;
    
    function myFunction(input) {
     // If input is a string
     if (typeof input === 'string') {
       // Try to convert string to number using the library
       const possibleNumber = wordsToNumbers(input);
      
       // If conversion was successful and result is a number
       if (typeof possibleNumber === 'number') {
         // Apply the same logic as numbers
         if (possibleNumber % 15 === 0) return 'pineapple';
         if (possibleNumber % 3 === 0) return 'pine';
         if (possibleNumber % 5 === 0) return 'apple';
         return possibleNumber;
       }
      
       // If not a number word, return greeting
       return `Hello ${input}`;
     }
      // If input is a number, apply the original logic
     if (input % 15 === 0) return 'pineapple';
     if (input % 3 === 0) return 'pine';
     if (input % 5 === 0) return 'apple';
     return input;
    }
    

    Code was working, but it could be improved. The Fizz Buzz logic was duplicated. Something satisfying to work with tests, is that I can ask AI for refactors on index.js knowing that any broken feature would be caught by index.test.js on terminal.

    I asked a final prompt:

    Extracting the numbers logic into a separate function would improve code readability and maintainability.

    const wordsToNumbers = require('words-to-numbers').wordsToNumbers;
    
    function processNumber(number) {
      if (number % 15 === 0) return 'pineapple';
      if (number % 3 === 0) return 'pine';
      if (number % 5 === 0) return 'apple';
      return number;
    }
    
    function myFunction(input) {
      // If input is a string
      if (typeof input === 'string') {
        // Try to convert string to number using the library
        const possibleNumber = wordsToNumbers(input);
        
        // If conversion was successful and result is a number
        if (typeof possibleNumber === 'number') {
          // Apply the same logic as numbers
          return processNumber(possibleNumber);
        }
        
        // If not a number word, return greeting
        return `Hello ${input}`;
      }
      
      // If input is a number, apply the original logic
      return processNumber(input);
    }
    
    module.exports = { myFunction }; 
    

    All tests passed:

    All tests passed

    Exercise 2

    Fizz Buzz was easy to test. I wanted to see if the same approach would work in a real-world scenario. So I applied the same testing principles to a React application, this time including an HTTP request.

    I used create-react-app and removed the boilerplate to start a blank application. The goal is to search a user with https://api.github.com/users/ and present the result.

    I added tests to App.test.js that cover the following:

    • Signals that “Github search” is readable from begin.
    • Mocks fetch.
    • Reads User Name from an input.
    • Clicks on the search button.
    • Requests the API with the User Name as parameter.
    • Reads “Loading…”.
    • Handles both success and failure scenarios.

    Then I prompted:

    Based on App.test.js update App.js as a React clean code expert.

    This was the resulting App.js. Being honest, I did not expect it to work on the first try. But that is the result I got out of the box:

    App Result

    The component’s logic works perfectly, but styling isn’t easily testable in unit tests. I decided to try asking the AI to improve the style and make it look like the actual Github page.

    Prompt Engineering Tip: Before using a prompt, ask AI to refine it for better results.

    Before:

    You are a great designer. Make this look great! Using @https://github.com/ aesthetics is welcome. But keep it minimal. Centralize and space elements, meaning to fill more of the screen. Replacing the Loading text with a loading icon is welcome.

    After:

    Transform this component into a visually polished design while preserving its core functionality. Key requirements:

    1. Aesthetic Approach:
      • Adopt GitHub’s clean, minimal design language (@https://github.com/)
      • Maintain functional simplicity while elevating visual appeal
    2. Layout Principles:
      • Center all elements vertically and horizontally
      • Maximize screen real estate usage with balanced spacing
    3. Create clear visual hierarchy
      • Specific Enhancements:
        • Replace “Loading…” text with a subtle animated spinner/icon
        • Use GitHub-inspired typography and color palette
        • Implement smooth state transitions
    4. Constraints:
      • Don’t alter the core data-fetching logic
      • Keep the component structure fundamentally the same
      • Maintain all existing functionality

    The result should feel like a native GitHub UI element — professional, understated, and highly functional.

    The result was actually very good:

    Styled Result

    GitHub Repository

    Code for both exercises is available on GitHub. Check the individual commits if you want to compare code between each step applied.

    GitHub - andregardi/tdd-ai: Using Test-Driven Development to Get Better AI-Generated Code

    Tags

    javascripttddaicursor

    Comments

    More Blog

    View all
    Cursor Automations in 2026: wire event-triggered coding agents to Slack, CI, and timerscursor

    Cursor Automations in 2026: wire event-triggered coding agents to Slack, CI, and timers

    Cursor Automations in 2026: wire event-triggered coding agents to Slack, CI, and...

    M
    Manu Shukla
    Index Everything, or Read Everything? The Dilemma of Feeding Specs to AI in Multi-Repo Developmentai

    Index Everything, or Read Everything? The Dilemma of Feeding Specs to AI in Multi-Repo Development

    The specs exist. The AI just can't see them. I've always been the type who builds hobby...

    S
    Shunya Shida
    Connect Claude Code, Cursor and Codex to Amazon Bedrock's new console (2026)amazonbedrock

    Connect Claude Code, Cursor and Codex to Amazon Bedrock's new console (2026)

    Connect Claude Code, Cursor and Codex to Amazon Bedrock's new console (2026) Summary. On 5...

    M
    Manu Shukla
    Spotting AI UI is too easyai

    Spotting AI UI is too easy

    There is a weird uncanny valley with LLM-generated UI right now. The code functions perfectly, but if...

    H
    Harish .s
    Seven ranking frameworks, one search page, zero translation tablesai

    Seven ranking frameworks, one search page, zero translation tables

    I went down a rabbit hole this morning reading the late-2025 Juejin AI roundups side by side, and the...

    N
    ninghonggang
    Zendesk MCP: Let Claude Handle Your Support Ticketsmcp

    Zendesk MCP: Let Claude Handle Your Support Tickets

    Install guide and config at curatedmcp.com Zendesk MCP: Let Claude Handle Your Support...

    C
    curatedmcp

    Stay up to date

    Get the latest Cursor prompts, rules, and resources delivered to your inbox weekly.

    Neura Market LogoNeura Market

    Discover the best AI prompts, plugins, and resources for Cursor and more.

    Content Types

    • Rules
    • Prompts
    • MCPs
    • Agents
    • Guides

    Platforms

    • ChatGPT Directory
    • Claude Directory
    • Gemini Directory
    • Cursor Directory
    • Grok Directory
    • Perplexity Directory
    • DeepSeek Directory
    • CoPilot Directory
    • Stable Diffusion Directory
    • Midjourney Directory
    • All Directories

    Resources

    • Blog
    • Documentation
    • Help Center
    • Marketplace

    Legal

    • Privacy Policy
    • Terms of Service

    © 2026 Neura Market. All rights reserved.

    |

    Not affiliated with any AI platform vendors.

    Neura Market

    Custom AI Systems & Services

    Our team of experienced AI builders will help build custom AI systems, workflows, and solutions for your business.

    Request custom work

    Ready-made automations for this

    Workflows from the Neura Market marketplace related to this Cursor resource

    • Learn JavaScript Coding with an Interactive RPG-Style Tutorial Gamen8n · $9.99 · Related topic
    • Automate Blog Engagement with GPT-5 Generated Comments for WordPressn8n · $4.99 · Related topic
    • Daily Auto-Generated Tweets from Trending Topics using Perplexity & GPT-4n8n · $4.99 · Related topic
    • Automate Google Cloud Storage with AI-Generated Images Using n8nn8n · $14.99 · Related topic
    Browse all workflows