Claude Code TDD गाइड: Vitest और node:test के साथ टेस्ट-ड्रिवन डेवलपमेंट
Claude Code के साथ TDD सीखें: Vitest, node:test, CI, hooks और prompt templates के उदाहरण।
Claude Code बहुत तेजी से कोड लिख सकता है, लेकिन तेज कोड हमेशा सुरक्षित बदलाव नहीं होता। असली समस्याएं अक्सर बाद में दिखती हैं: कोई edge case छूट गया, पुराना behavior टूट गया, coupon discount गलत निकला, या test सिर्फ CI में fail हुआ।
TDD, यानी test-driven development, इस गति को नियंत्रित करने का व्यावहारिक तरीका है। इसका चक्र है: पहले failing test लिखना, फिर सबसे छोटा implementation लिखना जिससे test pass हो, फिर behavior बदले बिना refactor करना। इसे Red-Green-Refactor कहा जाता है। Red का मतलब expected failure, Green का मतलब passing behavior, और Refactor का मतलब सफाई।
Claude Code इस workflow में अच्छा काम करता है क्योंकि यह test cases गिना सकता है, failure output पढ़ सकता है, minimum implementation बना सकता है और CI भी सेट कर सकता है। लेकिन सिर्फ “feature बना दो” लिखने से अक्सर implementation-first code बनता है और test बाद में चिपकाए जाते हैं। बेहतर तरीका है: पहले failing test दिखाओ, फिर implementation करो।
इस लेख को अपडेट करते समय आधिकारिक Claude Code hooks reference, Claude Code memory, Claude Code settings, Vitest Getting Started, Vitest CLI और Node.js test runner देखे गए। नीचे hook example JSON stdin से tool_input.file_path पढ़ता है, जो current Claude Code docs के अनुरूप है।
TDD में Claude Code की भूमिका
Claude Code test case बनाना, failure समझना, minimum implementation लिखना, CI जोड़ना और risk summary देना संभाल सकता है। Business rule, security boundary, public API contract और release decision इंसान को तय करना चाहिए।
| चरण | Claude Code का काम | इंसानी समीक्षा |
|---|---|---|
| Red | specification से failing tests लिखना | क्या उसने requirement invent की? |
| Green | minimum passing implementation | क्या extra abstraction आ गया? |
| Refactor | duplication और नाम साफ करना | behavior वही है? |
| CI | हर PR पर test चलाना | Node version सही है? |
| ऑपरेशन | hooks और CLAUDE.md लगाना | automation बहुत धीमा तो नहीं? |
flowchart LR
A["Specification छोटा करें"] --> B["Red: failing test"]
B --> C["Green: minimum implementation"]
C --> D["Refactor: cleanup"]
D --> E["CI और hooks फिर चलें"]
E --> B
उदाहरण 1: Vitest से price और coupon logic
Price, coupon और subscription logic TDD के लिए अच्छे candidates हैं, क्योंकि छोटी गलती revenue को प्रभावित कर सकती है।
npm install -D vitest
{
"type": "module",
"scripts": {
"test": "vitest run",
"test:watch": "vitest"
},
"devDependencies": {
"vitest": "^3.0.0"
}
}
पहले src/cart.test.ts बनाइए।
import { describe, expect, it } from "vitest";
import { priceCart, ValidationError } from "./cart";
describe("priceCart", () => {
it("calculates subtotal and total without a coupon", () => {
const result = priceCart({
items: [
{ sku: "book", unitPriceCents: 1200, quantity: 2 },
{ sku: "video", unitPriceCents: 3000, quantity: 1 },
],
});
expect(result).toEqual({
subtotalCents: 5400,
discountCents: 0,
totalCents: 5400,
});
});
it("applies a valid percent coupon", () => {
const result = priceCart(
{
items: [{ sku: "course", unitPriceCents: 10000, quantity: 1 }],
coupon: {
code: "SPRING20",
percentOff: 20,
expiresAt: "2026-06-30T00:00:00.000Z",
},
},
{ now: new Date("2026-06-02T00:00:00.000Z") },
);
expect(result.totalCents).toBe(8000);
expect(result.discountCents).toBe(2000);
});
it("rejects expired coupons", () => {
expect(() =>
priceCart(
{
items: [{ sku: "course", unitPriceCents: 10000, quantity: 1 }],
coupon: {
code: "OLD20",
percentOff: 20,
expiresAt: "2026-05-01T00:00:00.000Z",
},
},
{ now: new Date("2026-06-02T00:00:00.000Z") },
),
).toThrow(ValidationError);
});
it("rejects zero or negative quantity", () => {
expect(() =>
priceCart({
items: [{ sku: "book", unitPriceCents: 1200, quantity: 0 }],
}),
).toThrow("quantity must be positive");
});
});
Claude Code से Red confirm करवाइए।
हम Red stage में हैं। src/cart.test.ts मौजूद है, लेकिन src/cart.ts अभी नहीं है।
कृपया:
1. npm test चलाकर failure confirm करें।
2. test pass कराने के लिए minimum src/cart.ts implement करें।
3. UI, DB, external API या future feature न जोड़ें।
4. Green के बाद ही behavior बदले बिना refactor करें।
src/cart.ts का minimum implementation:
export class ValidationError extends Error {
constructor(message: string) {
super(message);
this.name = "ValidationError";
}
}
type CartItem = {
sku: string;
unitPriceCents: number;
quantity: number;
};
type Coupon = {
code: string;
percentOff: number;
expiresAt: string;
};
type CartInput = {
items: CartItem[];
coupon?: Coupon;
};
type PriceOptions = {
now?: Date;
};
export function priceCart(input: CartInput, options: PriceOptions = {}) {
if (input.items.length === 0) {
throw new ValidationError("cart must contain at least one item");
}
const subtotalCents = input.items.reduce((sum, item) => {
if (!Number.isInteger(item.quantity) || item.quantity <= 0) {
throw new ValidationError("quantity must be positive");
}
if (!Number.isInteger(item.unitPriceCents) || item.unitPriceCents < 0) {
throw new ValidationError("unitPriceCents must be a non-negative integer");
}
return sum + item.unitPriceCents * item.quantity;
}, 0);
const discountCents = calculateDiscount(subtotalCents, input.coupon, options.now ?? new Date());
return {
subtotalCents,
discountCents,
totalCents: subtotalCents - discountCents,
};
}
function calculateDiscount(subtotalCents: number, coupon: Coupon | undefined, now: Date) {
if (!coupon) return 0;
if (coupon.percentOff <= 0 || coupon.percentOff > 100) {
throw new ValidationError("percentOff must be between 1 and 100");
}
if (new Date(coupon.expiresAt).getTime() < now.getTime()) {
throw new ValidationError("coupon expired");
}
return Math.round(subtotalCents * (coupon.percentOff / 100));
}
उदाहरण 2: node:test से CLI boundary values
छोटे Node tools के लिए built-in node:test काफी है। इसे limit.test.mjs के रूप में save करें।
import test from "node:test";
import assert from "node:assert/strict";
export function parseLimit(value, fallback = 20) {
if (value === undefined || value === "") return fallback;
const parsed = Number(value);
if (!Number.isInteger(parsed)) {
throw new TypeError("limit must be an integer");
}
if (parsed < 1 || parsed > 100) {
throw new RangeError("limit must be between 1 and 100");
}
return parsed;
}
test("parseLimit uses fallback when the value is empty", () => {
assert.equal(parseLimit(undefined), 20);
assert.equal(parseLimit("", 50), 50);
});
test("parseLimit accepts values from 1 to 100", () => {
assert.equal(parseLimit("1"), 1);
assert.equal(parseLimit("100"), 100);
});
test("parseLimit rejects decimals and out-of-range values", () => {
assert.throws(() => parseLimit("1.5"), /integer/);
assert.throws(() => parseLimit("0"), /between 1 and 100/);
assert.throws(() => parseLimit("101"), /between 1 and 100/);
});
node --test limit.test.mjs
उदाहरण 3: API bug को regression test बनाना
Production bug मिले तो पहले उसे failing test में बदलें।
TDD से API regression test जोड़ें।
Context:
- POST /checkout expired coupon को गलती से accept कर रहा है।
- valid coupon और no-coupon checkout चलते रहने चाहिए।
Red:
- expired coupon पर 400 expect करने वाला test जोड़ें।
- current implementation में test fail हो यह confirm करें।
Green:
- API में smallest fix करें।
Refactor:
- सिर्फ duplicate date comparison निकालें।
Return:
- test name, failure output, changed files, commands, remaining risk.
आगे की योजना के लिए API testing guide और testing strategy guide भी देखें।
CI और hooks
name: test
on:
pull_request:
push:
branches: [main]
jobs:
unit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- run: npm test
Edit के बाद related Vitest चलाने के लिए hook:
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write|MultiEdit",
"hooks": [
{
"type": "command",
"command": "node .claude/hooks/run-related-vitest.mjs",
"timeout": 120
}
]
}
]
}
}
import { spawnSync } from "node:child_process";
import path from "node:path";
let raw = "";
for await (const chunk of process.stdin) {
raw += chunk;
}
const event = raw ? JSON.parse(raw) : {};
const filePath = event.tool_input?.file_path;
if (typeof filePath !== "string" || !/\.[cm]?[jt]sx?$/.test(filePath)) {
process.exit(0);
}
const target = path.isAbsolute(filePath)
? path.relative(process.cwd(), filePath)
: filePath;
const result = spawnSync("npx", ["vitest", "related", target, "--run"], {
stdio: "inherit",
shell: process.platform === "win32",
});
process.exit(result.status ?? 1);
CLAUDE.md में छोटा rule रखें।
## TDD workflow
- Behavior changes start with a failing test.
- Show the Red result before implementation.
- Implement the smallest change that makes the test pass.
- Refactor only after the targeted test is Green.
- Report the command, result, changed files, and remaining risk.
अधिक जानकारी के लिए hooks guide और CLAUDE.md best practices देखें।
Prompt templates
New feature TDD:
Goal:
Add [feature].
Spec:
- [happy path]
- [boundary values]
- [failure behavior]
Process:
1. Write tests first.
2. Run npm test and show Red.
3. Implement the smallest Green change.
4. Refactor without behavior change.
Return:
Failure output, commands, changed files, remaining risk.
Bug fix TDD:
Reproduction:
[input, action, or log]
Expected:
[correct behavior]
Current:
[current behavior]
Request:
Add a failing regression test first.
Then make the smallest fix.
Do not weaken or delete existing tests without explanation.
Safe refactor:
Target:
[file/function]
Constraint:
Public behavior must not change.
Steps:
1. Add characterization tests for current behavior.
2. Confirm Green.
3. Change internals only.
4. Re-run the same tests.
आम गलतियां
पहली गलती Red को skip करना है। अगर test fix से पहले ही pass है, तो वह bug नहीं पकड़ता। दूसरी गलती behavior की जगह implementation details test करना है। तीसरी गलती real time का use है; now inject करें। चौथी गलती mocks पर बहुत भरोसा करना है, खासकर payment, email और CRM में। पांचवीं गलती Claude Code को tests हटाकर Green पाने देना है।
CTA
एक price rule, एक CLI parser या एक API regression से शुरू करें। Solo developers free Claude Code cheatsheet और इन templates का उपयोग कर सकते हैं। Reusable prompts, hooks और review checklists के लिए ClaudeCodeLab products देखें। Teams जो real repository में TDD, CI, permissions और review workflow लागू करना चाहती हैं, वे Claude Code training and consultation देख सकती हैं।
वास्तव में आजमाने का परिणाम
Masa के workflow में Claude Code से पहले failing test लिखवाने पर review time घटा। Expired coupon, zero quantity और unauthenticated API cases पहले दिख गए। हर edit के बाद सभी tests चलाना hook में धीमा था, इसलिए practical setup यह रहा: edit के बाद related Vitest, और full E2E CI में।
मुफ़्त PDF: Claude Code cheatsheet
Email डालें और commands, review habits तथा safe workflow वाली एक-page PDF पाएँ.
हम आपका data सुरक्षित रखते हैं और spam नहीं भेजते.
लेखक के बारे में
Masa
Claude Code workflow और team adoption पर काम करने वाला engineer.
संबंधित लेख
Claude Code Obsidian to CLAUDE.md workflow: context बार-बार न समझाएं
Obsidian notes को CLAUDE.md operating notes में बदलकर Claude Code sessions को resume करना आसान बनाएं.
Claude Code Revenue CTA Routing: article से PDF, Gumroad और consultation तक
Reader intent के आधार पर free PDF, Gumroad products और consultation तक CTA route करने वाला workflow.
Claude Code टीम हैंडऑफ नियम: review proof, permissions, rollback और revenue path
Claude Code टीम काम के लिए evidence, permission rules, rollback, free PDF, Gumroad और consultation path वाला handoff.