Zum Hauptinhalt springen

Code-Tests mit Cursor: Unit, Integration und E2E

Cursor Testing

Tests sind der Grundstein zuverlässiger Softwareentwicklung. Die KI-Funktionen von Cursor können Ihnen helfen, umfassende Testsuiten zu schreiben, Randfälle zu identifizieren und die Testabdeckung aufrechtzuerhalten. Dieser Leitfaden deckt Unit-, Integrations- und End-to-End-Testworkflows ab.

Voraussetzungen​

Bevor Sie beginnen:

  • Cursor installiert (neueste Version empfohlen)
  • Eine Codebasis mit konfiguriertem Test-Framework
  • Vertrautheit mit Testkonzepten (Assertions, Mocks, Fixtures)

Test-Setup in Cursor​

Projektstruktur​

project/
src/
components/
utils/
api/
tests/
unit/ # Unit-Tests
integration/ # Integrationstests
e2e/ # End-to-End-Tests
jest.config.js
playwright.config.ts
vitest.config.ts

Jest mit TypeScript konfigurieren​

// jest.config.js
module.exports = {
preset: 'ts-jest',
testEnvironment: 'jsdom',
setupFilesAfterEnv: ['<rootDir>/tests/setup.ts'],
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1',
'\\.(css|less|scss)$': 'identity-obj-proxy',
},
collectCoverageFrom: [
'src/**/*.{ts,tsx}',
'!src/**/*.d.ts',
'!src/**/index.ts',
],
coverageThreshold: {
global: {
branches: 80,
functions: 80,
lines: 80,
statements: 80,
},
},
};

Unit-Tests mit KI schreiben​

Tests aus Code generieren​

Wählen Sie einen Code-Snippet und verwenden Sie den Ctrl+L Befehl von Cursor:

Schreibe umfassende Unit-Tests für diese Funktion:
- Happy-Path
- Edge-Cases (leere Eingabe, sehr große Werte, Sonderzeichen)
- Fehlerbehandlung
- Grenzwerte

Beispiel: Testen von Utility-Funktionen​

// src/utils/validation.ts
export const isValidEmail = (email: string): boolean => {
const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return regex.test(email);
};

export const formatDate = (
date: Date,
format: string = 'YYYY-MM-DD'
): string => {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');

return format
.replace('YYYY', String(year))
.replace('MM', month)
.replace('DD', day);
};

Cursor generiert Tests:

// tests/unit/validation.test.ts
import { isValidEmail, formatDate } from '@/utils/validation';

describe('isValidEmail', () => {
it('returns true for valid email', () => {
expect(isValidEmail('[email protected]')).toBe(true);
expect(isValidEmail('[email protected]')).toBe(true);
});

it('returns false for invalid email', () => {
expect(isValidEmail('')).toBe(false);
expect(isValidEmail('not-an-email')).toBe(false);
expect(isValidEmail('@domain.com')).toBe(false);
expect(isValidEmail('user@')).toBe(false);
expect(isValidEmail('user@domain')).toBe(false);
});

it('handles edge cases', () => {
expect(isValidEmail('[email protected]')).toBe(true);
expect(isValidEmail('[email protected]')).toBe(true);
});
});

describe('formatDate', () => {
it('formats date with default format', () => {
const date = new Date('2024-03-15');
expect(formatDate(date)).toBe('2024-03-15');
});

it('formats date with custom format', () => {
const date = new Date('2024-03-15');
expect(formatDate(date, 'DD/MM/YYYY')).toBe('15/03/2024');
expect(formatDate(date, 'MM-DD-YYYY')).toBe('03-15-2024');
});

it('handles edge cases', () => {
const janFirst = new Date('2024-01-01');
expect(formatDate(janFirst)).toBe('2024-01-01');

const dec31 = new Date('2024-12-31');
expect(formatDate(dec31)).toBe('2024-12-31');
});
});

React-Komponenten testen​

// tests/unit/Button.test.tsx
import { render, screen, fireEvent } from '@testing-library/react';
import { Button } from '@/components/Button';

describe('Button', () => {
it('renders with correct text', () => {
render(<Button>Click me</Button>);
expect(screen.getByText('Click me')).toBeInTheDocument();
});

it('calls onClick when clicked', () => {
const handleClick = jest.fn();
render(<Button onClick={handleClick}>Click me</Button>);

fireEvent.click(screen.getByText('Click me'));
expect(handleClick).toHaveBeenCalledTimes(1);
});

it('is disabled when loading', () => {
render(<Button isLoading>Loading</Button>);
expect(screen.getByRole('button')).toBeDisabled();
});

it('shows loading spinner when isLoading is true', () => {
render(<Button isLoading>Loading</Button>);
expect(screen.getByTestId('spinner')).toBeInTheDocument();
});
});

Integrationstests​

API-Endpunkte testen​

// tests/integration/api.test.ts
import request from 'supertest';
import { app } from '@/app';
import { prisma } from '@/db';

describe('API Integration Tests', () => {
beforeEach(async () => {
await prisma.user.deleteMany();
});

afterAll(async () => {
await prisma.$disconnect();
});

describe('POST /api/users', () => {
it('creates a new user', async () => {
const response = await request(app)
.post('/api/users')
.send({
name: 'Test User',
password: 'password123',
})
.expect(201);

expect(response.body.data.email).toBe('[email protected]');
});

it('returns 400 for invalid data', async () => {
await request(app)
.post('/api/users')
.send({
email: 'invalid',
name: '',
})
.expect(400);
});
});
});

Datenbankinteraktionen testen​

// tests/integration/database.test.ts
import { UserRepository } from '@/repositories/UserRepository';
import { prisma } from '@/db';

describe('UserRepository', () => {
let repository: UserRepository;

beforeEach(() => {
repository = new UserRepository();
});

afterEach(async () => {
await prisma.user.deleteMany();
});

it('creates and retrieves a user', async () => {
const user = await repository.create({
name: 'Test User',
});

expect(user.id).toBeDefined();

const found = await repository.findById(user.id);
expect(found?.email).toBe('[email protected]');
});
});

End-to-End-Tests mit Playwright​

Playwright einrichten​

npm init playwright@latest

E2E-Tests generieren​

// tests/e2e/login.spec.ts
import { test, expect } from '@playwright/test';

test.describe('Authentication Flow', () => {
test('user can log in', async ({ page }) => {
await page.goto('/login');

await page.fill('[data-testid="email-input"]', '[email protected]');
await page.fill('[data-testid="password-input"]', 'password123');
await page.click('[data-testid="login-button"]');

await expect(page).toHaveURL('/dashboard');
await expect(page.locator('[data-testid="welcome-message"]')).toContainText(
'Welcome'
);
});

test('shows error for invalid credentials', async ({ page }) => {
await page.goto('/login');

await page.fill('[data-testid="email-input"]', '[email protected]');
await page.fill('[data-testid="password-input"]', 'wrongpassword');
await page.click('[data-testid="login-button"]');

await expect(page.locator('[data-testid="error-message"]')).toContainText(
'Invalid credentials'
);
});
});

Page Object Pattern mit Cursor​

// tests/e2e/pages/LoginPage.ts
import { Page, Locator } from '@playwright/test';

export class LoginPage {
readonly emailInput: Locator;
readonly passwordInput: Locator;
readonly loginButton: Locator;
readonly errorMessage: Locator;

constructor(private page: Page) {
this.emailInput = page.locator('[data-testid="email-input"]');
this.passwordInput = page.locator('[data-testid="password-input"]');
this.loginButton = page.locator('[data-testid="login-button"]');
this.errorMessage = page.locator('[data-testid="error-message"]');
}

async goto() {
await this.page.goto('/login');
}

async login(email: string, password: string) {
await this.emailInput.fill(email);
await this.passwordInput.fill(password);
await this.loginButton.click();
}
}

Test-Driven Development mit Cursor​

Rot-Grün-Refactor-Zyklus​

  1. Rot: Schreiben Sie einen Test, der das erwartete Verhalten beschreibt
  2. Grün: Verwenden Sie Cursor, um den Implementierungscode zu generieren
  3. Refactor: Bitten Sie Cursor, den Code zu bereinigen, während die Tests weiterhin bestehen

Beispiel: TDD mit Cursor​

// Schritt 1: Schreiben Sie den Test
// tests/unit/calculator.test.ts
import { Calculator } from '@/utils/Calculator';

describe('Calculator', () => {
it('adds two numbers', () => {
const calc = new Calculator();
expect(calc.add(2, 3)).toBe(5);
});

it('handles negative numbers', () => {
const calc = new Calculator();
expect(calc.add(-2, 3)).toBe(1);
});
});
// Schritt 2: Cursor generiert die Implementierung
// src/utils/Calculator.ts
export class Calculator {
add(a: number, b: number): number {
return a + b;
}
}

Mocks und Stubs​

Jest Mocks​

// tests/unit/api.test.ts
import { fetchUserData } from '@/api/users';
import { getDatabaseConnection } from '@/db';

jest.mock('@/db', () => ({
getDatabaseConnection: jest.fn(),
}));

describe('fetchUserData', () => {
it('returns user data from database', async () => {
const mockQuery = jest.fn().mockResolvedValue({
rows: [{ id: 1, name: 'Test User' }],
});

(getDatabaseConnection as jest.Mock).mockReturnValue({
query: mockQuery,
});

const result = await fetchUserData(1);
expect(result).toEqual({ id: 1, name: 'Test User' });
expect(mockQuery).toHaveBeenCalledWith(
'SELECT * FROM users WHERE id = $1',
[1]
);
});
});

MSW für API-Mocking​

// tests/mocks/handlers.ts
import { rest } from 'msw';

export const handlers = [
rest.get('/api/users', (req, res, ctx) => {
return res(
ctx.json({
users: [
{ id: 1, name: 'Test User' },
{ id: 2, name: 'Another User' },
],
})
);
}),

rest.post('/api/users', async (req, res, ctx) => {
const body = await req.json();
return res(
ctx.status(201),
ctx.json({ id: 3, ...body })
);
}),
];

Testabdeckung und Qualität​

Abdeckungsberichte generieren​

# Jest
npx jest --coverage

# Vitest
npx vitest --coverage

# In Cursor anzeigen
# Klicken Sie auf den HTML-Berichtslink im Terminal

Abdeckungsanalyse durch Cursor​

Analysiere diese Testsuite:
1. Welche Edge-Cases werden von den Tests abgedeckt?
2. Welche Testlücken gibt es?
3. Wie kann die Branch-Abdeckung verbessert werden?

Continuous Integration Setup​

GitHub Actions​

# .github/workflows/test.yml
name: Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npm run test:unit
- run: npm run test:integration
- run: npm run test:e2e

Kurzreferenz für Tests​

FrameworkVerwendungCursor Prompt
JestUnit/Integration"Schreibe einen Jest-Test für diese Komponente"
VitestSchnelle Unit-Tests"Generiere Vitest-Tests, die Edge-Cases abdecken"
PlaywrightE2E Browser"Erstelle einen Playwright-Test für den Login-Flow"
CypressE2E Browser"Schreibe einen Cypress-Test für Formular-Submit"
MSWAPI Mocking"Konfiguriere MSW-Handler für die User-API"
React Testing LibraryKomponententests"Teste diese React-Komponente mit RTL"

Häufige Test-Patterns​

PatternBeispiel
Factory-FunktionencreateUser({ role: 'admin' })
Setup/TeardownbeforeEach / afterEach
Parametrisierte Testsit.each([[1, 2, 3], [4, 5, 9]])
Snapshot-Testsexpect(tree).toMatchSnapshot()
Spiesjest.spyOn(console, 'error')

Verwandte Ressourcen​

Zuletzt aktualisiert: Juli 2025