Skip to content

Test-Driven Development - Cursor IDE

You’re building a financial calculation engine for a investment platform. Requirements include compound interest calculations, portfolio rebalancing algorithms, tax optimization strategies, and risk assessment. The calculations must be 100% accurate, handle edge cases, and be thoroughly documented. Your team requires TDD approach with >95% test coverage.

By completing this lesson, you’ll master:

  • Writing tests before implementation with AI
  • Creating comprehensive test suites efficiently
  • Using AI to discover edge cases
  • Property-based testing with AI assistance
  • Test documentation and maintenance
  • Performance and integration testing
  • Understanding of testing concepts
  • Basic knowledge of Jest/Vitest
  • Completed previous lessons
  • Calculator or finance domain knowledge helpful
  • Optional: Playwright MCP for browser testing (see setup)

Build a calculation engine using pure TDD:

  • Write all tests before implementation
  • Achieve 100% code coverage
  • Handle all edge cases
  • Create property-based tests
  • Document test scenarios
  • Ensure calculation accuracy
  1. Define Test Strategy

Start with requirements analysis:

"I need to build a financial calculation engine with these features:
1. Compound interest calculator
2. Portfolio rebalancing
3. Tax loss harvesting
4. Risk assessment (Sharpe ratio, etc.)
Help me create a comprehensive test plan following TDD principles.
What test categories and scenarios should I consider?"
  1. Create Test Structure
"Design the test file structure for:
- Unit tests for each calculation
- Integration tests for workflows
- Property-based tests for mathematical properties
- Performance tests for large portfolios
- Snapshot tests for reports
Create the directory structure and test templates"
  1. Generate Test Utilities

Switch to Agent mode:

"Create test utilities and helpers:
- Test data factories for portfolios
- Assertion helpers for financial values
- Mock data generators
- Custom matchers for precision
- Test fixtures for common scenarios"

Example test utilities:

test-utils/financial.ts
export const expectFinanciallyEqual = (
actual: number,
expected: number,
precision: number = 2
) => {
const multiplier = Math.pow(10, precision);
expect(Math.round(actual * multiplier)).toBe(
Math.round(expected * multiplier)
);
};
export const createPortfolio = (overrides?: Partial<Portfolio>): Portfolio => ({
id: faker.string.uuid(),
name: faker.company.name() + ' Portfolio',
holdings: [
{
symbol: 'AAPL',
shares: faker.number.int({ min: 10, max: 1000 }),
costBasis: faker.number.float({ min: 100, max: 200 }),
},
{
symbol: 'GOOGL',
shares: faker.number.int({ min: 5, max: 500 }),
costBasis: faker.number.float({ min: 1000, max: 3000 }),
},
],
cash: faker.number.float({ min: 1000, max: 100000 }),
...overrides,
});
export const createMarketData = (): MarketData => ({
AAPL: { price: 150.00, change: 0.02 },
GOOGL: { price: 2800.00, change: -0.01 },
// ... more symbols
});
  1. Test Compound Interest Calculator
"Write comprehensive tests for compound interest calculation:
- Basic calculation with annual compounding
- Different compounding frequencies (monthly, daily, continuous)
- Edge cases (negative rates, zero principal, extreme values)
- Precision and rounding behavior
- Invalid input handling
Include the mathematical formula in comments"

Example test suite:

__tests__/calculators/compound-interest.test.ts
describe('CompoundInterestCalculator', () => {
describe('calculate()', () => {
// Formula: A = P(1 + r/n)^(nt)
// A = final amount, P = principal, r = rate, n = compounds per year, t = time
it('should calculate simple annual compound interest', () => {
const result = calculateCompoundInterest({
principal: 1000,
rate: 0.05,
time: 10,
compoundingFrequency: 1,
});
// 1000 * (1 + 0.05/1)^(1*10) = 1628.89
expectFinanciallyEqual(result.finalAmount, 1628.89);
expectFinanciallyEqual(result.totalInterest, 628.89);
});
it('should handle monthly compounding', () => {
const result = calculateCompoundInterest({
principal: 1000,
rate: 0.05,
time: 10,
compoundingFrequency: 12,
});
// 1000 * (1 + 0.05/12)^(12*10) = 1647.01
expectFinanciallyEqual(result.finalAmount, 1647.01);
});
it('should handle continuous compounding', () => {
const result = calculateCompoundInterest({
principal: 1000,
rate: 0.05,
time: 10,
compoundingFrequency: 'continuous',
});
// P * e^(rt) = 1000 * e^(0.05*10) = 1648.72
expectFinanciallyEqual(result.finalAmount, 1648.72);
});
describe('edge cases', () => {
it('should handle zero principal', () => {
const result = calculateCompoundInterest({
principal: 0,
rate: 0.05,
time: 10,
});
expect(result.finalAmount).toBe(0);
});
it('should handle negative interest rates', () => {
const result = calculateCompoundInterest({
principal: 1000,
rate: -0.02,
time: 5,
});
expectFinanciallyEqual(result.finalAmount, 904.84);
});
it('should handle very large numbers without overflow', () => {
const result = calculateCompoundInterest({
principal: 1e10,
rate: 0.15,
time: 50,
});
expect(result.finalAmount).toBeGreaterThan(0);
expect(result.finalAmount).toBeLessThan(Infinity);
});
});
describe('validation', () => {
it('should throw for invalid principal', () => {
expect(() =>
calculateCompoundInterest({
principal: NaN,
rate: 0.05,
time: 10,
})
).toThrow('Principal must be a valid number');
});
it('should throw for invalid time period', () => {
expect(() =>
calculateCompoundInterest({
principal: 1000,
rate: 0.05,
time: -5,
})
).toThrow('Time period must be positive');
});
});
});
});
  1. Test Portfolio Rebalancing
@test-utils/financial.ts
"Create tests for portfolio rebalancing algorithm:
- Target allocation rebalancing
- Threshold-based rebalancing
- Tax-aware rebalancing
- Transaction cost minimization
- Edge cases (illiquid assets, constraints)
Test both the algorithm and its optimizations"
  1. Test Risk Calculations
"Write tests for risk metrics:
- Sharpe ratio calculation
- Standard deviation of returns
- Maximum drawdown
- Value at Risk (VaR)
- Beta calculation
Include tests for different time periods and data quality"
  1. Define Properties
"Create property-based tests for financial calculations:
- Mathematical properties (associativity, distributivity)
- Invariants (portfolio value = sum of holdings + cash)
- Bounds (returns between -100% and +∞)
- Monotonicity (more time = more compound interest)
Use fast-check library"

Example property tests:

__tests__/properties/calculations.property.test.ts
import fc from 'fast-check';
describe('Financial Calculations Properties', () => {
describe('Compound Interest Properties', () => {
it('should always increase with positive rate and time', () => {
fc.assert(
fc.property(
fc.float({ min: 100, max: 1000000 }), // principal
fc.float({ min: 0.001, max: 0.20 }), // rate
fc.integer({ min: 1, max: 50 }), // years
(principal, rate, time) => {
const result = calculateCompoundInterest({
principal,
rate,
time,
});
expect(result.finalAmount).toBeGreaterThan(principal);
expect(result.totalInterest).toBeGreaterThan(0);
}
)
);
});
it('should be monotonic with respect to time', () => {
fc.assert(
fc.property(
fc.float({ min: 100, max: 1000000 }),
fc.float({ min: 0.001, max: 0.20 }),
fc.integer({ min: 1, max: 30 }),
fc.integer({ min: 1, max: 20 }),
(principal, rate, time1, extraTime) => {
const time2 = time1 + extraTime;
const result1 = calculateCompoundInterest({
principal, rate, time: time1
});
const result2 = calculateCompoundInterest({
principal, rate, time: time2
});
expect(result2.finalAmount).toBeGreaterThan(result1.finalAmount);
}
)
);
});
});
describe('Portfolio Properties', () => {
it('should maintain total value through rebalancing', () => {
fc.assert(
fc.property(
fc.array(
fc.record({
symbol: fc.string({ minLength: 1, maxLength: 5 }),
shares: fc.integer({ min: 1, max: 1000 }),
price: fc.float({ min: 1, max: 5000 }),
}),
{ minLength: 2, maxLength: 10 }
),
fc.float({ min: 0, max: 100000 }),
(holdings, cash) => {
const portfolio = { holdings, cash };
const totalBefore = calculatePortfolioValue(portfolio);
const rebalanced = rebalancePortfolio(portfolio, {
STOCKS: 0.6,
BONDS: 0.3,
CASH: 0.1,
});
const totalAfter = calculatePortfolioValue(rebalanced);
// Account for transaction costs
expect(totalAfter).toBeGreaterThanOrEqual(totalBefore * 0.99);
expect(totalAfter).toBeLessThanOrEqual(totalBefore);
}
)
);
});
});
});
  1. Test Invariants
"Generate tests for system invariants:
- Conservation of value in transactions
- No negative holdings after rebalancing
- Risk metrics within valid ranges
- Tax calculations never negative
Create property tests for each invariant"
  1. Fuzz Testing
"Create fuzz tests for:
- Input validation boundaries
- Calculation precision limits
- Concurrent operations
- State consistency
Generate random but valid test data"

Phase 3.5: Browser Testing with Playwright MCP

Section titled “Phase 3.5: Browser Testing with Playwright MCP”
  1. Configure Playwright MCP
~/.cursor/mcp.json
{
"mcpServers": {
"playwright": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-puppeteer"]
}
}
}
  1. E2E Testing with MCP
"Using Playwright MCP, test the investment dashboard:
1. Navigate to localhost:3000
2. Log in with test credentials
3. Verify portfolio value displays correctly
4. Click 'Rebalance' button
5. Take screenshot of confirmation modal
6. Verify success message appears"
// MCP handles browser automation
"Using Playwright MCP:
- Fill the compound interest form with principal=10000, rate=5%, time=10
- Click Calculate button
- Verify result shows $16,288.95
- Take screenshot for visual regression test"
  1. Visual Regression Testing
"Using Playwright MCP:
- Navigate to component library page
- Screenshot each calculator component
- Compare with baseline images
- Report any visual differences"
  1. Accessibility Testing
"Using Playwright MCP, run accessibility audit:
- Navigate to each page
- Run axe accessibility scan
- Check color contrast ratios
- Verify keyboard navigation
- Test screen reader announcements
- Generate accessibility report"
  1. Performance Testing via Browser
"Using Playwright MCP, measure performance:
- Navigate to dashboard with performance tracing
- Measure time to interactive (TTI)
- Check largest contentful paint (LCP)
- Monitor cumulative layout shift (CLS)
- Generate performance report with metrics"
// Real user monitoring simulation
"Simulate user journey with Playwright MCP:
1. Land on homepage (measure load time)
2. Navigate to calculator (measure transition)
3. Perform 10 calculations (measure responsiveness)
4. Generate report (measure rendering time)
Record all performance metrics"

Parallel Testing:

"Using Playwright MCP, run tests in parallel:
- Test 1: Portfolio rebalancing flow
- Test 2: Tax calculation workflow
- Test 3: Report generation
- Test 4: User settings update
Run all simultaneously and report results"

API Mocking:

"Using Playwright MCP with network interception:
- Mock market data API responses
- Test error scenarios (500, timeout)
- Verify error handling UI
- Test loading states
- Validate retry mechanisms"

State Management Testing:

"Test complex state with Playwright MCP:
- Open app in two browser tabs
- Update portfolio in tab 1
- Verify tab 2 reflects changes
- Test optimistic updates
- Verify conflict resolution"

Phase 4: Integration and Performance Tests

Section titled “Phase 4: Integration and Performance Tests”
  1. Integration Test Scenarios
"Create integration tests for complete workflows:
- New investor onboarding with initial portfolio
- Monthly rebalancing with market updates
- Tax loss harvesting at year end
- Performance reporting generation
Test the full flow with realistic data"

Example integration test:

__tests__/integration/investor-workflow.test.ts
describe('Investor Workflow Integration', () => {
let investor: Investor;
let marketData: MarketDataService;
beforeEach(() => {
investor = createInvestor({
initialDeposit: 100000,
riskTolerance: 'moderate',
taxBracket: 0.32,
});
marketData = new MockMarketDataService();
});
it('should handle complete monthly rebalancing workflow', async () => {
// Initial portfolio creation
const portfolio = await createPortfolio(investor, {
strategy: 'aggressive-growth',
constraints: {
minCash: 5000,
maxSinglePosition: 0.25,
},
});
expect(portfolio.holdings).toHaveLength(15);
expectPortfolioValid(portfolio);
// Simulate month of market movements
await marketData.simulateMonth();
// Check for rebalancing need
const analysis = analyzePortfolio(portfolio, marketData);
expect(analysis.rebalancingNeeded).toBe(true);
expect(analysis.drift).toBeGreaterThan(0.05);
// Execute rebalancing
const trades = await rebalancePortfolio(portfolio, {
marketData,
taxAware: true,
minTradeSize: 100,
});
expect(trades).toHaveLength(8);
expect(trades.every(t => t.taxImpact !== undefined)).toBe(true);
// Apply trades and verify
const newPortfolio = applyTrades(portfolio, trades);
expectPortfolioValid(newPortfolio);
expect(calculateDrift(newPortfolio)).toBeLessThan(0.01);
});
});
  1. Performance Tests
"Create performance benchmarks:
- Calculate 10,000 portfolios in under 1 second
- Rebalance 1,000 asset portfolio in under 100ms
- Generate tax report for 1 year in under 500ms
- Risk calculations on 5 years of data in under 50ms
Include memory usage tests"
  1. Load Tests
"Design load tests for:
- Concurrent portfolio calculations
- Market data updates during rebalancing
- Multiple tax optimization requests
- Report generation under load
Ensure thread safety and accuracy"

Phase 5: Test Maintenance and Documentation

Section titled “Phase 5: Test Maintenance and Documentation”
  1. Generate Test Documentation
"Create comprehensive test documentation:
- Test coverage report with explanations
- Edge case catalog with examples
- Performance benchmark baselines
- Test data generation guide
- Troubleshooting guide for failures"
  1. Create Visual Test Reports
"Build visual test reporting:
- Coverage heat maps
- Performance trend graphs
- Flaky test detection
- Test execution timeline
- Failure pattern analysis"
  1. Implement Test Helpers
"Create advanced test helpers:
- Snapshot testing for calculations
- Golden file testing for reports
- Mutation testing setup
- Contract testing for APIs
- Regression test automation"

Technique 1: AI-Driven Test Discovery with MCP

Section titled “Technique 1: AI-Driven Test Discovery with MCP”

Use AI and MCP to find edge cases:

// Method 1: Using Playwright MCP for UI testing
"Using Playwright MCP, explore the calculator UI and find:
- Input validation edge cases
- UI states not covered by unit tests
- Accessibility issues
- Performance bottlenecks in rendering"
// Method 2: Using database MCP for data testing
"Using PostgreSQL MCP, analyze the schema and suggest:
- Constraint violation test cases
- Transaction isolation tests needed
- Performance test scenarios
- Data integrity edge cases"
// Method 3: Manual implementation analysis
@implementation/calculator.ts
"Analyze this implementation and suggest:
1. Missing test cases
2. Potential edge cases
3. Error conditions not handled
4. Performance bottlenecks
5. Precision issues"

Follow strict TDD cycle:

// 1. Write failing test
it('should calculate tax-loss harvesting savings', () => {
const result = calculateTaxLossHarvesting({
losses: 5000,
gains: 8000,
taxRate: 0.32,
});
expect(result.taxSavings).toBe(960); // (5000 - 3000) * 0.32
});
// 2. See it fail
// ❌ calculateTaxLossHarvesting is not defined
// 3. Implement minimum to pass
function calculateTaxLossHarvesting({ losses, gains, taxRate }) {
const netLoss = Math.min(losses, gains);
return { taxSavings: netLoss * taxRate };
}
// 4. Refactor with confidence

Ensure test quality:

// Configure Stryker for mutation testing
{
"mutator": {
"name": "typescript",
"excludedMutations": ["StringLiteral"]
},
"testRunner": "jest",
"coverageAnalysis": "perTest",
"thresholds": { "high": 90, "low": 85, "break": 80 }
}

Problem: Tests break with minor refactoring

Solution:

// Bad: Testing implementation details
it('should call Math.pow', () => {
const spy = jest.spyOn(Math, 'pow');
calculateCompoundInterest({ ... });
expect(spy).toHaveBeenCalled();
});
// Good: Testing behavior
it('should calculate correct result', () => {
const result = calculateCompoundInterest({ ... });
expectFinanciallyEqual(result.finalAmount, 1628.89);
});

Advanced testing techniques:

  1. Contract Testing

    • Consumer-driven contracts
    • Schema validation
    • API compatibility tests
    • Breaking change detection
  2. Chaos Testing

    • Random failure injection
    • Network latency simulation
    • Memory pressure tests
    • Concurrency stress tests
  3. Visual Testing

    • Screenshot regression tests
    • Chart rendering validation
    • Report format verification
    • Cross-browser visual tests
  4. MCP-Powered Testing

    • Use BrowserStack MCP for cloud device testing
    • Implement SonarQube MCP for code quality gates
    • Add Debugg.AI MCP for AI-driven test generation
    • Create custom MCP server for test orchestration

Your TDD implementation succeeds when:

  • ✅ 100% code coverage achieved
  • ✅ All edge cases documented and tested
  • ✅ Tests run in under 30 seconds
  • ✅ Zero flaky tests
  • ✅ Mutation score >85%
  • ✅ Property tests find no violations
  • ✅ Performance benchmarks met
  • ✅ Documentation comprehensive

Teams using AI-assisted TDD report:

  • 90% fewer production bugs
  • 60% faster development velocity
  • 95% confidence in refactoring
  • 50% reduction in debugging time

Before writing implementation:

  • Requirements clearly defined
  • Test structure created
  • Edge cases identified
  • Test data factories ready
  • Assertions planned
  • Performance criteria set
  • Documentation template ready
  • CI/CD pipeline configured
  1. Tests First, Always: Never write code without a failing test
  2. AI for Discovery: Use AI to find cases you’d miss
  3. Properties Over Examples: Property tests catch more bugs
  4. Test the Contract: Not the implementation
  5. Fast Feedback: Keep tests fast and focused
  • Test planning: 2 hours
  • Unit test creation: 4 hours
  • Property tests: 2 hours
  • Integration tests: 2 hours
  • Test utilities: 2 hours
  • Total: ~12 hours (yields 40+ hours saved in debugging)

You’ve mastered TDD with AI. Ready for more?

Mutation Testing

Set up advanced mutation testing

Test Automation

Build AI-powered test generation

Performance Testing

Create comprehensive performance suite

Continue to Performance Optimization →