

Also from Kynth Studios


Also from Kynth Studios


Also from Kynth Studios
1# Testing & TDD — Cursor Rules2# Comprehensive rules for test-driven development across languages and frameworks34## Project Context5You are working on a project that prioritizes test-driven development (TDD). Tests are6written before implementation, code is designed for testability, and the test suite serves7as living documentation. The goal is high confidence in code correctness through8well-structured, maintainable tests.910## Tech Stack (Multi-Framework)11- JavaScript/TypeScript: Jest, Vitest, React Testing Library, Playwright12- Python: pytest, unittest, pytest-cov, factory_boy13- General: MSW (Mock Service Worker), Faker for test data14- CI integration for automated test runs1516## TDD Workflow1718### The Red-Green-Refactor Cycle191. **Red**: Write a failing test that describes the desired behavior202. **Green**: Write the minimum code to make the test pass213. **Refactor**: Clean up the code while keeping tests green224. Repeat2324### Rules25- Never write production code without a failing test first26- Each test should test ONE behavior or requirement27- Run the full test suite before committing28- Treat test code with the same quality standards as production code29- Tests should be fast — mock expensive I/O operations3031## Naming Conventions3233### Test Files34- JavaScript: `*.test.ts`, `*.spec.ts` (co-located with source)35- Python: `test_*.py` or `*_test.py` in `tests/` directory36- Test fixtures/factories: `factories.ts`, `conftest.py`3738### Test Names — Describe Behavior, Not Implementation39```ts40// GOOD — describes what should happen41it('returns 404 when the user does not exist')42it('sends a confirmation email after successful registration')43it('prevents duplicate orders within 5 minutes')44it('shows an error message when the form submission fails')4546// BAD — describes implementation details47it('calls findById with correct id')48it('sets isLoading to true')49it('dispatches SET_USER action')50```5152### Test Structure — AAA Pattern53```ts54it('calculates the total with tax for items in the cart', () => {55 // Arrange — set up test data and dependencies56 const cart = new Cart();57 cart.addItem({ name: 'Widget', price: 10.00, quantity: 2 });58 cart.addItem({ name: 'Gadget', price: 25.00, quantity: 1 });5960 // Act — perform the action being tested61 const total = cart.calculateTotal({ taxRate: 0.08 });6263 // Assert — verify the expected outcome64 expect(total).toBe(48.60);65});66```6768## Test Categories6970### Unit Tests71- Test individual functions, classes, or modules in isolation72- Mock all external dependencies (database, APIs, file system)73- Should run in milliseconds74- Aim for high coverage of business logic and utility functions7576### Integration Tests77- Test how modules work together78- May use a real database (test instance) or API79- Test the full request/response cycle for API endpoints80- Slower than unit tests but provide higher confidence8182### End-to-End (E2E) Tests83- Test complete user workflows through the UI84- Use Playwright or Cypress85- Test critical paths: sign up, purchase flow, key features86- Keep the E2E suite small — focus on high-value user journeys8788### The Testing Pyramid89```90 / E2E \ Few — slow, expensive, high confidence91 / Integr. \ Some — medium speed, good confidence92 / Unit \ Many — fast, cheap, focused93```9495## Mocking Strategy9697### What to Mock98- External APIs and services99- Database calls (in unit tests)100- File system operations101- Time/dates (use fake timers)102- Random number generation103- Email/notification services104105### What NOT to Mock106- The code under test itself107- Simple utility functions108- Data structures and models109- Things that are fast and deterministic110111### Mock Patterns112```ts113// Prefer dependency injection over module mocking114class OrderService {115 constructor(116 private db: Database, // Inject — easy to mock117 private emailService: EmailService,118 ) {}119}120121// In tests:122const mockDb = { findById: vi.fn(), save: vi.fn() };123const mockEmail = { send: vi.fn() };124const service = new OrderService(mockDb, mockEmail);125```126127```ts128// MSW for API mocking (intercepts at the network level)129import { http, HttpResponse } from 'msw';130import { setupServer } from 'msw/node';131132const server = setupServer(133 http.get('/api/users/:id', ({ params }) => {134 return HttpResponse.json({ id: params.id, name: 'Alice' });135 }),136);137138beforeAll(() => server.listen());139afterEach(() => server.resetHandlers());140afterAll(() => server.close());141```142143## React/UI Testing144145### Testing Library Philosophy146- Test what the user sees and does, not component internals147- Query by role, label, text — not by CSS class or test ID148- Prefer `userEvent` over `fireEvent` for realistic interactions149150```tsx151import { render, screen } from '@testing-library/react';152import userEvent from '@testing-library/user-event';153154it('shows validation error when submitting empty form', async () => {155 const user = userEvent.setup();156 render(<LoginForm onSubmit={vi.fn()} />);157158 await user.click(screen.getByRole('button', { name: /sign in/i }));159160 expect(screen.getByText(/email is required/i)).toBeInTheDocument();161});162163it('calls onSubmit with form data when valid', async () => {164 const user = userEvent.setup();165 const handleSubmit = vi.fn();166 render(<LoginForm onSubmit={handleSubmit} />);167168 await user.type(screen.getByLabelText(/email/i), 'test@example.com');169 await user.type(screen.getByLabelText(/password/i), 'secure123');170 await user.click(screen.getByRole('button', { name: /sign in/i }));171172 expect(handleSubmit).toHaveBeenCalledWith({173 email: 'test@example.com',174 password: 'secure123',175 });176});177```178179## Test Data Management180- Use factories for test data generation (factory_boy, fishery)181- Use Faker for realistic random data182- Create minimal test data — only the fields relevant to the test183- Use builder patterns for complex object creation184- Reset database state between tests (transactions or truncation)185186```ts187// factories.ts188import { faker } from '@faker-js/faker';189190export function buildUser(overrides: Partial<User> = {}): User {191 return {192 id: faker.string.uuid(),193 email: faker.internet.email(),194 name: faker.person.fullName(),195 createdAt: faker.date.past(),196 ...overrides,197 };198}199```200201## Error and Edge Case Testing202- Test error paths, not just happy paths203- Test boundary conditions (empty arrays, zero values, max lengths)204- Test concurrent operations when relevant205- Test authorization: users accessing resources they don't own206- Test invalid input: wrong types, missing fields, malformed data207208## Performance209- Tests should run in seconds, not minutes210- Parallelize test execution where possible211- Mock slow I/O in unit tests212- Use `beforeAll` for expensive setup shared across tests213- Profile slow tests with `--verbose` or timing reporters214215## Common Pitfalls216- Testing implementation details instead of behavior (brittle tests)217- Shared mutable state between tests (flaky tests)218- Not resetting mocks between tests (`vi.restoreAllMocks()`)219- Over-mocking — testing that mocks return what you told them to return220- Snapshot testing for dynamic content (snapshots break constantly)221- Ignoring test failures — fix or delete, never skip permanently222- Not testing async error paths (unhandled rejections in tests)223- Writing tests after code is done (loses TDD benefits)224
One repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| survivorforge/cursor-rulesrules/ai-ml-python/.cursorrules · 17 | .cursorrules | teststylearchdeployment+2 | 81/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/api-microservices/.cursorrules · 17 | .cursorrules | buildteststylearch+5 | 92/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/database-sql/.cursorrules · 17 | .cursorrules | styletypessecuritydatabase+3 | 65/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/devops-docker/.cursorrules · 17 | .cursorrules | setupbuildteststyle+4 | 93/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/devops-infrastructure/.cursorrules · 17 | .cursorrules | buildteststylesecurity+3 | 93/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/django-rest/.cursorrules · 17 | .cursorrules | buildteststylearch+5 | 84/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/docker-devops/.cursorrules · 17 | .cursorrules | setupteststylearch+6 | 85/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/flutter-dart/.cursorrules · 17 | .cursorrules | teststylearchtypes+5 | 89/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/go-gin/.cursorrules · 17 | .cursorrules | testlint-formatstylearch+5 | 84/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/langchain-ai/.cursorrules · 17 | .cursorrules | testlint-formatstylearch+4 | 84/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/mobile-react-native/.cursorrules · 17 | .cursorrules | teststylearchtypes+7 | 89/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/nextjs-14-app-router/.cursorrules · 17 | .cursorrules | teststyletypestesting-strategy+3 | 71/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/nextjs-app-router/.cursorrules · 17 | .cursorrules | teststylearchtypes+5 | 81/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/nextjs-typescript/.cursorrules · 17 | .cursorrules | teststylearchtypes+5 | 81/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/nextjs/.cursorrules · 17 | .cursorrules | teststylearchtypes+5 | 81/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/nodejs-express-typescript/.cursorrules · 17 | .cursorrules | setupteststylearch+7 | 81/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/nodejs-express/.cursorrules · 17 | .cursorrules | testlint-formatstylearch+7 | 92/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/performance-optimization/.cursorrules · 17 | .cursorrules | styledatabaseapiperformance+2 | 65/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/python-django/.cursorrules · 17 | .cursorrules | testlint-formatstylearch+6 | 99/100 | 13 days ago | |
| survivorforge/cursor-rulesrules/python-fastapi/.cursorrules · 17 | .cursorrules | testlint-formatstylearch+6 | 99/100 | 13 days ago |
A badge carrying the measured quality of the strongest agent config file in this repository, out of 100. It reads from this index every time somebody loads your page, so it changes when the measurement changes and there is nothing to keep up to date. Free, no account, and the value is not something you or we can set by hand.
[](https://rulestack.kynth.studio/configs/survivorforge-cursor-rules-rules-testing-tdd-cursorrules)Would rather not hotlink us? Every badge is also served in shields.io’s endpoint schema, so shields renders the image and your readers never talk to our domain:
Published by Toolproof, the masthead over this index and eight others. The method behind the number is at toolproof.kynth.studio/methodology, and the whole thing is readable as JSON with no key at /api.