Skip to main content
RapidDev - Software Development Agency
cursor-tutorial

Can Cursor Be Used for Test-Driven Development

Use Cursor for test-driven development by following the TDD Super-Prompt pattern: instruct Composer to write failing tests first, commit them, then generate implementation code in a separate session. Cursor's Agent mode with YOLO enabled creates an automated test-code-iterate loop that runs tests, identifies failures, and fixes code until all tests pass.

What you'll learn

  • How to execute the TDD Super-Prompt workflow in Cursor
  • How to generate failing tests before writing implementation
  • How to use YOLO mode for automated test-fix loops
  • How to separate test and implementation generation for better results
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate8 min read15-20 minCursor Pro+, any test runnerMarch 2026RapidDev Engineering Team
TL;DR

Use Cursor for test-driven development by following the TDD Super-Prompt pattern: instruct Composer to write failing tests first, commit them, then generate implementation code in a separate session. Cursor's Agent mode with YOLO enabled creates an automated test-code-iterate loop that runs tests, identifies failures, and fixes code until all tests pass.

Test-Driven Development with Cursor's Agent Mode

Test-driven development works exceptionally well with Cursor because the AI can both write tests and iterate on implementation until tests pass. The key insight is separating the two phases: first generate tests that define desired behavior, then generate implementation code constrained to pass those tests. This prevents the common AI pitfall of writing tests that simply validate whatever implementation was generated. This tutorial covers the complete TDD workflow in Cursor.

Prerequisites

  • Cursor installed (Pro for Agent mode and YOLO)
  • A test runner configured (Vitest, Jest, pytest, go test)
  • Basic understanding of TDD red-green-refactor cycle
  • YOLO mode enabled in Cursor Settings for test commands

Step-by-step guide

1

Define the specification as a prompt

Start by writing a clear specification of what the function or module should do. Open Composer (Cmd+I) and describe the expected behavior, inputs, outputs, and edge cases. Tell Cursor explicitly to write only tests, not implementation.

Cursor Composer prompt
1// Prompt to type in Cursor Composer (Cmd+I):
2// Write ONLY test cases for a calculateShipping function.
3// DO NOT write the implementation.
4//
5// Specification:
6// - Takes: { weight: number (kg), destination: 'domestic' | 'international' }
7// - Returns: { cost: number (cents), estimatedDays: number }
8// - Domestic: $5 base + $1/kg, 3-5 business days
9// - International: $15 base + $3/kg, 7-14 business days
10// - Free shipping for domestic orders over 10kg
11// - Maximum weight: 30kg (throw error if exceeded)
12// - Weight must be positive (throw error if zero or negative)
13//
14// Write tests covering ALL these rules plus edge cases.
15// Use Vitest. Run with: npx vitest run src/utils/shipping.test.ts

Pro tip: The phrase 'DO NOT write the implementation' is critical. Without it, Cursor will generate both tests and code together, producing tests that validate the implementation rather than the specification.

Expected result: Cursor generates a complete test file with tests for every specification rule and edge case, all initially failing.

2

Review and commit the test file

Review the generated tests to ensure they cover all specification requirements. Run them to confirm they all fail (red phase). Then commit the tests to Git before writing any implementation. This creates a clear checkpoint and prevents the tests from being modified during implementation.

Terminal commands
1// After reviewing the generated tests, run them:
2// npx vitest run src/utils/shipping.test.ts
3// All tests should FAIL (red phase)
4//
5// Then commit:
6// git add src/utils/shipping.test.ts
7// git commit -m "test: add shipping calculator test suite (TDD red phase)"

Pro tip: Committing tests before implementation creates a Git safety net. If the implementation goes wrong, you can reset to this commit and try again with a different approach.

Expected result: All tests fail as expected and are committed to Git as a baseline.

3

Generate implementation in a new Composer session

Start a FRESH Composer session (Cmd+N then Cmd+I) to implement the function. Reference the test file with @file and instruct Cursor to write code that passes all tests. The critical instruction is: do not modify the tests.

Cursor Composer prompt
1// Prompt to type in a NEW Cursor Composer session (Cmd+I):
2// @src/utils/shipping.test.ts
3// Write the implementation for calculateShipping in
4// src/utils/shipping.ts that passes ALL tests in the test file.
5// Requirements:
6// - DO NOT modify the test file
7// - Run npx vitest run src/utils/shipping.test.ts after each change
8// - Keep iterating until ALL tests pass
9// - If a test seems wrong, tell me — do not change it

Pro tip: Using a FRESH session prevents context bleed from the test-writing phase. The implementation agent should only see the tests as specifications, not the reasoning behind them.

Expected result: Cursor generates the implementation, runs tests, and iterates until all tests pass (green phase).

4

Enable YOLO mode for automated test loops

Enable YOLO mode in Cursor Settings to let the agent automatically run test commands without asking permission each time. Add your test runner to the allowed commands list. This creates a fast automated loop: write code, run tests, read failures, fix code, repeat.

Cursor Settings
1// In Cursor Settings → Features → YOLO Mode:
2// Enable YOLO mode
3// Allowed commands: vitest, jest, npm test, pytest, go test
4//
5// With YOLO enabled, the Composer agent will:
6// 1. Write implementation code
7// 2. Automatically run vitest
8// 3. Read test output
9// 4. Fix failures
10// 5. Re-run tests
11// 6. Repeat until all green

Pro tip: YOLO mode combined with TDD is the most powerful Cursor workflow. The agent operates in a tight feedback loop that mirrors how experienced TDD practitioners work, but at AI speed.

Expected result: The agent runs tests automatically after each code change, iterating until all tests pass without manual intervention.

5

Refactor with test protection

Once all tests pass (green phase), start the refactor phase. Open a new Chat (Cmd+L), reference both files, and ask Cursor to improve the implementation while keeping all tests passing. This is the TDD refactor step where code quality improves without changing behavior.

Cursor Chat prompt
1// Prompt to type in Cursor Chat (Cmd+L):
2// @src/utils/shipping.ts @src/utils/shipping.test.ts
3// Refactor the shipping calculator for better readability:
4// - Extract magic numbers into named constants
5// - Improve error messages
6// - Add TypeScript types for inputs and outputs
7// - Simplify any complex conditional logic
8// ALL tests must continue to pass after refactoring.
9// Do not change the public function signature.

Expected result: Cursor refactors the code for quality while maintaining all test passes.

Complete working example

src/utils/shipping.test.ts
1import { describe, it, expect } from 'vitest';
2import { calculateShipping } from './shipping';
3
4describe('calculateShipping', () => {
5 describe('domestic shipping', () => {
6 it('should calculate base rate plus per-kg cost', () => {
7 const result = calculateShipping({ weight: 5, destination: 'domestic' });
8 expect(result.cost).toBe(1000); // $5 base + $1*5kg = $10 = 1000 cents
9 });
10
11 it('should estimate 3-5 business days', () => {
12 const result = calculateShipping({ weight: 1, destination: 'domestic' });
13 expect(result.estimatedDays).toBeGreaterThanOrEqual(3);
14 expect(result.estimatedDays).toBeLessThanOrEqual(5);
15 });
16
17 it('should be free for orders over 10kg', () => {
18 const result = calculateShipping({ weight: 11, destination: 'domestic' });
19 expect(result.cost).toBe(0);
20 });
21
22 it('should not be free at exactly 10kg', () => {
23 const result = calculateShipping({ weight: 10, destination: 'domestic' });
24 expect(result.cost).toBeGreaterThan(0);
25 });
26 });
27
28 describe('international shipping', () => {
29 it('should calculate international rate', () => {
30 const result = calculateShipping({ weight: 5, destination: 'international' });
31 expect(result.cost).toBe(3000); // $15 base + $3*5kg = $30 = 3000 cents
32 });
33
34 it('should estimate 7-14 business days', () => {
35 const result = calculateShipping({ weight: 1, destination: 'international' });
36 expect(result.estimatedDays).toBeGreaterThanOrEqual(7);
37 expect(result.estimatedDays).toBeLessThanOrEqual(14);
38 });
39 });
40
41 describe('validation', () => {
42 it('should throw for weight over 30kg', () => {
43 expect(() => calculateShipping({ weight: 31, destination: 'domestic' }))
44 .toThrow('exceeds maximum');
45 });
46
47 it('should throw for zero weight', () => {
48 expect(() => calculateShipping({ weight: 0, destination: 'domestic' }))
49 .toThrow('must be positive');
50 });
51
52 it('should throw for negative weight', () => {
53 expect(() => calculateShipping({ weight: -1, destination: 'domestic' }))
54 .toThrow('must be positive');
55 });
56 });
57});

Common mistakes

Why it's a problem: Generating tests and implementation in the same Composer session

How to avoid: Always use separate Composer sessions: one for tests (red), one for implementation (green). Commit tests before starting implementation.

Why it's a problem: Not telling Cursor 'DO NOT write implementation'

How to avoid: Include 'DO NOT write the implementation' or 'Write ONLY test cases' in your test generation prompt.

Why it's a problem: Allowing Cursor to modify tests during the implementation phase

How to avoid: Add 'DO NOT modify the test file' to the implementation prompt. Commit tests to Git first so changes are visible in diff.

Best practices

  • Separate test generation and implementation into distinct Composer sessions
  • Commit tests to Git before starting implementation to create a safety checkpoint
  • Use YOLO mode with your test runner for automated test-code-iterate loops
  • Tell Cursor 'DO NOT modify the test file' during the implementation phase
  • Write specifications as bullet points before generating tests for complete coverage
  • Use a fresh Composer session for the refactor phase to avoid context pollution
  • Start with the simplest test cases and progress to edge cases for incremental TDD

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

Write a comprehensive test suite for a calculateShipping function with these rules: [paste specification]. Use Vitest with describe/it blocks. Cover happy paths, edge cases, boundary values, and error conditions. DO NOT write the implementation.

Cursor Prompt

Write ONLY test cases (no implementation) for a calculateShipping function. Spec: domestic = $5 base + $1/kg (3-5 days), international = $15 base + $3/kg (7-14 days), free domestic over 10kg, max weight 30kg, positive weight required. Use Vitest. Cover all rules plus edge cases. Run with npx vitest run.

Frequently asked questions

Can Cursor be used for test-driven development?

Yes. Cursor is highly effective for TDD when you follow the two-session pattern: generate tests first in one Composer session, commit them, then generate implementation in a fresh session. The agent's ability to run tests and iterate makes the red-green-refactor cycle faster than manual TDD.

What is the TDD Super-Prompt pattern?

It is a workflow where you describe the specification, instruct Cursor to write tests first (without implementation), then in a separate session ask it to write code that passes all tests. With YOLO mode, Cursor iterates automatically until all tests pass.

Does TDD work with Cursor for any language?

Yes. The pattern works with Vitest, Jest, pytest, go test, RSpec, JUnit, or any test runner. Specify your test runner in the prompt and in .cursorrules. Enable YOLO mode for the test command.

How do I prevent Cursor from cheating on tests?

Cursor 'cheats' by modifying tests to match its implementation. Prevent this by committing tests to Git first and adding 'DO NOT modify the test file' to the implementation prompt. Review the Git diff to catch any test modifications.

Should I use Chat or Composer for TDD?

Use Composer (Cmd+I) for both phases because it can create and edit files. Agent mode with YOLO enabled handles the test-run-fix loop automatically. Chat (Cmd+L) is better for the refactor phase where you want discussion before changes.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.