@aicgen/aicgen 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +7 -2
- package/claude.md +1 -1
- package/dist/index.js +6272 -5503
- package/package.json +1 -1
- package/.agent/rules/api-design.md +0 -649
- package/.agent/rules/architecture.md +0 -2507
- package/.agent/rules/best-practices.md +0 -622
- package/.agent/rules/code-style.md +0 -308
- package/.agent/rules/design-patterns.md +0 -577
- package/.agent/rules/devops.md +0 -230
- package/.agent/rules/error-handling.md +0 -417
- package/.agent/rules/instructions.md +0 -28
- package/.agent/rules/language.md +0 -786
- package/.agent/rules/performance.md +0 -710
- package/.agent/rules/security.md +0 -587
- package/.agent/rules/testing.md +0 -572
- package/.agent/workflows/add-documentation.md +0 -10
- package/.agent/workflows/generate-integration-tests.md +0 -10
- package/.agent/workflows/generate-unit-tests.md +0 -11
- package/.agent/workflows/performance-audit.md +0 -11
- package/.agent/workflows/refactor-extract-module.md +0 -12
- package/.agent/workflows/security-audit.md +0 -12
- package/.gemini/instructions.md +0 -4843
package/.agent/rules/testing.md
DELETED
|
@@ -1,572 +0,0 @@
|
|
|
1
|
-
# Testing Rules
|
|
2
|
-
|
|
3
|
-
# Unit Testing Fundamentals
|
|
4
|
-
|
|
5
|
-
## Arrange-Act-Assert Pattern
|
|
6
|
-
|
|
7
|
-
```typescript
|
|
8
|
-
describe('UserService', () => {
|
|
9
|
-
it('should create user with hashed password', async () => {
|
|
10
|
-
// Arrange - Set up test data and dependencies
|
|
11
|
-
const userData = { email: 'test@example.com', password: 'secret123' };
|
|
12
|
-
const mockRepo = { save: jest.fn().mockResolvedValue({ id: '1', ...userData }) };
|
|
13
|
-
const service = new UserService(mockRepo);
|
|
14
|
-
|
|
15
|
-
// Act - Execute the behavior being tested
|
|
16
|
-
const result = await service.createUser(userData);
|
|
17
|
-
|
|
18
|
-
// Assert - Verify the outcomes
|
|
19
|
-
expect(result.id).toBe('1');
|
|
20
|
-
expect(mockRepo.save).toHaveBeenCalledWith(
|
|
21
|
-
expect.objectContaining({ email: 'test@example.com' })
|
|
22
|
-
);
|
|
23
|
-
});
|
|
24
|
-
});
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
## Test Observable Behavior, Not Implementation
|
|
28
|
-
|
|
29
|
-
```typescript
|
|
30
|
-
// ❌ Bad: Testing implementation details
|
|
31
|
-
it('should call validateEmail method', () => {
|
|
32
|
-
const spy = jest.spyOn(service, 'validateEmail');
|
|
33
|
-
service.createUser({ email: 'test@example.com' });
|
|
34
|
-
expect(spy).toHaveBeenCalled();
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
// ✅ Good: Testing observable behavior
|
|
38
|
-
it('should reject invalid email', async () => {
|
|
39
|
-
await expect(
|
|
40
|
-
service.createUser({ email: 'invalid-email' })
|
|
41
|
-
).rejects.toThrow('Invalid email format');
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
it('should accept valid email', async () => {
|
|
45
|
-
const result = await service.createUser({ email: 'valid@example.com' });
|
|
46
|
-
expect(result.email).toBe('valid@example.com');
|
|
47
|
-
});
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
## One Assertion Per Test Concept
|
|
51
|
-
|
|
52
|
-
```typescript
|
|
53
|
-
// ❌ Bad: Multiple unrelated assertions
|
|
54
|
-
it('should validate user input', () => {
|
|
55
|
-
expect(() => validate({ age: -1 })).toThrow();
|
|
56
|
-
expect(() => validate({ age: 200 })).toThrow();
|
|
57
|
-
expect(() => validate({ name: '' })).toThrow();
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
// ✅ Good: One test per scenario
|
|
61
|
-
it('should reject negative age', () => {
|
|
62
|
-
expect(() => validate({ age: -1 })).toThrow('Age must be positive');
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
it('should reject age over 150', () => {
|
|
66
|
-
expect(() => validate({ age: 200 })).toThrow('Age must be under 150');
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
it('should reject empty name', () => {
|
|
70
|
-
expect(() => validate({ name: '' })).toThrow('Name is required');
|
|
71
|
-
});
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
## Descriptive Test Names
|
|
75
|
-
|
|
76
|
-
```typescript
|
|
77
|
-
// ❌ Vague names
|
|
78
|
-
it('should work correctly', () => {});
|
|
79
|
-
it('handles edge case', () => {});
|
|
80
|
-
|
|
81
|
-
// ✅ Descriptive names - describe the scenario and expected outcome
|
|
82
|
-
it('should return empty array when no users match filter', () => {});
|
|
83
|
-
it('should throw ValidationError when email is empty', () => {});
|
|
84
|
-
it('should retry failed payment up to 3 times before giving up', () => {});
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
## Tests Should Be Independent
|
|
88
|
-
|
|
89
|
-
```typescript
|
|
90
|
-
// ❌ Bad: Tests depend on each other
|
|
91
|
-
let userId: string;
|
|
92
|
-
|
|
93
|
-
it('should create user', async () => {
|
|
94
|
-
const user = await service.createUser(data);
|
|
95
|
-
userId = user.id; // Shared state!
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
it('should update user', async () => {
|
|
99
|
-
await service.updateUser(userId, newData); // Depends on previous test
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
// ✅ Good: Each test is self-contained
|
|
103
|
-
it('should update user', async () => {
|
|
104
|
-
const user = await service.createUser(data);
|
|
105
|
-
const updated = await service.updateUser(user.id, newData);
|
|
106
|
-
expect(updated.name).toBe(newData.name);
|
|
107
|
-
});
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
## Test Edge Cases
|
|
111
|
-
|
|
112
|
-
```typescript
|
|
113
|
-
describe('divide', () => {
|
|
114
|
-
it('should divide two positive numbers', () => {
|
|
115
|
-
expect(divide(10, 2)).toBe(5);
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
it('should throw when dividing by zero', () => {
|
|
119
|
-
expect(() => divide(10, 0)).toThrow('Division by zero');
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
it('should handle negative numbers', () => {
|
|
123
|
-
expect(divide(-10, 2)).toBe(-5);
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
it('should return zero when numerator is zero', () => {
|
|
127
|
-
expect(divide(0, 5)).toBe(0);
|
|
128
|
-
});
|
|
129
|
-
});
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
---
|
|
134
|
-
|
|
135
|
-
# Test Doubles and Mocking
|
|
136
|
-
|
|
137
|
-
## Types of Test Doubles
|
|
138
|
-
|
|
139
|
-
```typescript
|
|
140
|
-
// STUB: Returns canned responses
|
|
141
|
-
const stubUserRepo = {
|
|
142
|
-
findById: () => ({ id: '1', name: 'Test User' })
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
// MOCK: Pre-programmed with expectations
|
|
146
|
-
const mockPaymentGateway = {
|
|
147
|
-
charge: jest.fn()
|
|
148
|
-
.mockResolvedValueOnce({ success: true, transactionId: 'tx1' })
|
|
149
|
-
.mockResolvedValueOnce({ success: false, error: 'Declined' })
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
// SPY: Records calls for verification
|
|
153
|
-
const spy = jest.spyOn(emailService, 'send');
|
|
154
|
-
|
|
155
|
-
// FAKE: Working implementation (not for production)
|
|
156
|
-
class FakeDatabase implements Database {
|
|
157
|
-
private data = new Map<string, any>();
|
|
158
|
-
|
|
159
|
-
async save(id: string, entity: any) { this.data.set(id, entity); }
|
|
160
|
-
async find(id: string) { return this.data.get(id); }
|
|
161
|
-
}
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
## When to Mock
|
|
165
|
-
|
|
166
|
-
```typescript
|
|
167
|
-
// ✅ Mock external services (APIs, databases)
|
|
168
|
-
const mockHttpClient = {
|
|
169
|
-
get: jest.fn().mockResolvedValue({ data: userData })
|
|
170
|
-
};
|
|
171
|
-
|
|
172
|
-
// ✅ Mock time-dependent operations
|
|
173
|
-
jest.useFakeTimers();
|
|
174
|
-
jest.setSystemTime(new Date('2024-01-15'));
|
|
175
|
-
|
|
176
|
-
// ✅ Mock random/non-deterministic functions
|
|
177
|
-
jest.spyOn(Math, 'random').mockReturnValue(0.5);
|
|
178
|
-
|
|
179
|
-
// ❌ Don't mock the code you're testing
|
|
180
|
-
// ❌ Don't mock simple data structures
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
## Mock Verification
|
|
184
|
-
|
|
185
|
-
```typescript
|
|
186
|
-
it('should send welcome email after registration', async () => {
|
|
187
|
-
const mockEmail = { send: jest.fn().mockResolvedValue(true) };
|
|
188
|
-
const service = new UserService({ emailService: mockEmail });
|
|
189
|
-
|
|
190
|
-
await service.register({ email: 'new@example.com' });
|
|
191
|
-
|
|
192
|
-
expect(mockEmail.send).toHaveBeenCalledWith({
|
|
193
|
-
to: 'new@example.com',
|
|
194
|
-
template: 'welcome',
|
|
195
|
-
subject: 'Welcome!'
|
|
196
|
-
});
|
|
197
|
-
expect(mockEmail.send).toHaveBeenCalledTimes(1);
|
|
198
|
-
});
|
|
199
|
-
```
|
|
200
|
-
|
|
201
|
-
## Partial Mocks
|
|
202
|
-
|
|
203
|
-
```typescript
|
|
204
|
-
// Mock only specific methods
|
|
205
|
-
const service = new OrderService();
|
|
206
|
-
|
|
207
|
-
jest.spyOn(service, 'validateOrder').mockReturnValue(true);
|
|
208
|
-
jest.spyOn(service, 'calculateTotal').mockReturnValue(100);
|
|
209
|
-
// Other methods use real implementation
|
|
210
|
-
|
|
211
|
-
const result = await service.processOrder(orderData);
|
|
212
|
-
expect(result.total).toBe(100);
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
## Resetting Mocks
|
|
216
|
-
|
|
217
|
-
```typescript
|
|
218
|
-
describe('PaymentService', () => {
|
|
219
|
-
const mockGateway = { charge: jest.fn() };
|
|
220
|
-
const service = new PaymentService(mockGateway);
|
|
221
|
-
|
|
222
|
-
beforeEach(() => {
|
|
223
|
-
jest.clearAllMocks(); // Clear call history
|
|
224
|
-
// or jest.resetAllMocks() to also reset return values
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
it('should process payment', async () => {
|
|
228
|
-
mockGateway.charge.mockResolvedValue({ success: true });
|
|
229
|
-
await service.charge(100);
|
|
230
|
-
expect(mockGateway.charge).toHaveBeenCalledTimes(1);
|
|
231
|
-
});
|
|
232
|
-
});
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
## Mock Modules
|
|
236
|
-
|
|
237
|
-
```typescript
|
|
238
|
-
// Mock entire module
|
|
239
|
-
jest.mock('./email-service', () => ({
|
|
240
|
-
EmailService: jest.fn().mockImplementation(() => ({
|
|
241
|
-
send: jest.fn().mockResolvedValue(true)
|
|
242
|
-
}))
|
|
243
|
-
}));
|
|
244
|
-
|
|
245
|
-
// Mock with partial implementation
|
|
246
|
-
jest.mock('./config', () => ({
|
|
247
|
-
...jest.requireActual('./config'),
|
|
248
|
-
API_KEY: 'test-key'
|
|
249
|
-
}));
|
|
250
|
-
```
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
---
|
|
254
|
-
|
|
255
|
-
# Integration Testing
|
|
256
|
-
|
|
257
|
-
## Testing Real Dependencies
|
|
258
|
-
|
|
259
|
-
```typescript
|
|
260
|
-
describe('UserRepository Integration', () => {
|
|
261
|
-
let db: Database;
|
|
262
|
-
let repository: UserRepository;
|
|
263
|
-
|
|
264
|
-
beforeAll(async () => {
|
|
265
|
-
db = await createTestDatabase();
|
|
266
|
-
repository = new UserRepository(db);
|
|
267
|
-
});
|
|
268
|
-
|
|
269
|
-
afterAll(async () => {
|
|
270
|
-
await db.close();
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
beforeEach(async () => {
|
|
274
|
-
await db.clear('users'); // Clean slate for each test
|
|
275
|
-
});
|
|
276
|
-
|
|
277
|
-
it('should persist and retrieve user', async () => {
|
|
278
|
-
const userData = { email: 'test@example.com', name: 'Test User' };
|
|
279
|
-
|
|
280
|
-
const created = await repository.create(userData);
|
|
281
|
-
const found = await repository.findById(created.id);
|
|
282
|
-
|
|
283
|
-
expect(found).toEqual(expect.objectContaining(userData));
|
|
284
|
-
});
|
|
285
|
-
});
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
## API Integration Tests
|
|
289
|
-
|
|
290
|
-
```typescript
|
|
291
|
-
describe('POST /api/users', () => {
|
|
292
|
-
let app: Express;
|
|
293
|
-
let db: Database;
|
|
294
|
-
|
|
295
|
-
beforeAll(async () => {
|
|
296
|
-
db = await createTestDatabase();
|
|
297
|
-
app = createApp(db);
|
|
298
|
-
});
|
|
299
|
-
|
|
300
|
-
afterEach(async () => {
|
|
301
|
-
await db.clear('users');
|
|
302
|
-
});
|
|
303
|
-
|
|
304
|
-
it('should create user and return 201', async () => {
|
|
305
|
-
const response = await request(app)
|
|
306
|
-
.post('/api/users')
|
|
307
|
-
.send({ email: 'new@example.com', name: 'New User' })
|
|
308
|
-
.expect(201);
|
|
309
|
-
|
|
310
|
-
expect(response.body.data).toEqual(
|
|
311
|
-
expect.objectContaining({
|
|
312
|
-
email: 'new@example.com',
|
|
313
|
-
name: 'New User'
|
|
314
|
-
})
|
|
315
|
-
);
|
|
316
|
-
|
|
317
|
-
// Verify in database
|
|
318
|
-
const user = await db.findOne('users', { email: 'new@example.com' });
|
|
319
|
-
expect(user).toBeTruthy();
|
|
320
|
-
});
|
|
321
|
-
|
|
322
|
-
it('should return 400 for invalid email', async () => {
|
|
323
|
-
const response = await request(app)
|
|
324
|
-
.post('/api/users')
|
|
325
|
-
.send({ email: 'invalid', name: 'Test' })
|
|
326
|
-
.expect(400);
|
|
327
|
-
|
|
328
|
-
expect(response.body.error.code).toBe('VALIDATION_ERROR');
|
|
329
|
-
});
|
|
330
|
-
});
|
|
331
|
-
```
|
|
332
|
-
|
|
333
|
-
## Database Transaction Testing
|
|
334
|
-
|
|
335
|
-
```typescript
|
|
336
|
-
describe('OrderService Integration', () => {
|
|
337
|
-
it('should rollback on payment failure', async () => {
|
|
338
|
-
const order = await orderService.createOrder({ items: [...] });
|
|
339
|
-
|
|
340
|
-
// Mock payment to fail
|
|
341
|
-
paymentGateway.charge.mockRejectedValue(new Error('Declined'));
|
|
342
|
-
|
|
343
|
-
await expect(
|
|
344
|
-
orderService.processOrder(order.id)
|
|
345
|
-
).rejects.toThrow('Payment failed');
|
|
346
|
-
|
|
347
|
-
// Verify order status unchanged
|
|
348
|
-
const updatedOrder = await orderRepository.findById(order.id);
|
|
349
|
-
expect(updatedOrder.status).toBe('pending');
|
|
350
|
-
|
|
351
|
-
// Verify inventory not deducted
|
|
352
|
-
const inventory = await inventoryRepository.findByProductId(productId);
|
|
353
|
-
expect(inventory.quantity).toBe(originalQuantity);
|
|
354
|
-
});
|
|
355
|
-
});
|
|
356
|
-
```
|
|
357
|
-
|
|
358
|
-
## Test Data Builders
|
|
359
|
-
|
|
360
|
-
```typescript
|
|
361
|
-
class UserBuilder {
|
|
362
|
-
private data: Partial<User> = {
|
|
363
|
-
email: 'default@example.com',
|
|
364
|
-
name: 'Default User',
|
|
365
|
-
role: 'user'
|
|
366
|
-
};
|
|
367
|
-
|
|
368
|
-
withEmail(email: string) { this.data.email = email; return this; }
|
|
369
|
-
withRole(role: string) { this.data.role = role; return this; }
|
|
370
|
-
asAdmin() { this.data.role = 'admin'; return this; }
|
|
371
|
-
|
|
372
|
-
build(): User { return this.data as User; }
|
|
373
|
-
|
|
374
|
-
async save(db: Database): Promise<User> {
|
|
375
|
-
return db.insert('users', this.data);
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
// Usage
|
|
380
|
-
const admin = await new UserBuilder()
|
|
381
|
-
.withEmail('admin@example.com')
|
|
382
|
-
.asAdmin()
|
|
383
|
-
.save(db);
|
|
384
|
-
```
|
|
385
|
-
|
|
386
|
-
## Test Isolation
|
|
387
|
-
|
|
388
|
-
```typescript
|
|
389
|
-
// Use transactions that rollback
|
|
390
|
-
describe('IntegrationTests', () => {
|
|
391
|
-
beforeEach(async () => {
|
|
392
|
-
await db.beginTransaction();
|
|
393
|
-
});
|
|
394
|
-
|
|
395
|
-
afterEach(async () => {
|
|
396
|
-
await db.rollbackTransaction();
|
|
397
|
-
});
|
|
398
|
-
});
|
|
399
|
-
|
|
400
|
-
// Or use test containers
|
|
401
|
-
import { PostgreSqlContainer } from '@testcontainers/postgresql';
|
|
402
|
-
|
|
403
|
-
let container: PostgreSqlContainer;
|
|
404
|
-
|
|
405
|
-
beforeAll(async () => {
|
|
406
|
-
container = await new PostgreSqlContainer().start();
|
|
407
|
-
db = await connect(container.getConnectionUri());
|
|
408
|
-
});
|
|
409
|
-
|
|
410
|
-
afterAll(async () => {
|
|
411
|
-
await container.stop();
|
|
412
|
-
});
|
|
413
|
-
```
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
---
|
|
417
|
-
|
|
418
|
-
# Testing Basics
|
|
419
|
-
|
|
420
|
-
## Your First Unit Test
|
|
421
|
-
|
|
422
|
-
A unit test verifies that a small piece of code works correctly.
|
|
423
|
-
|
|
424
|
-
```pseudocode
|
|
425
|
-
// Function to test
|
|
426
|
-
function add(a, b):
|
|
427
|
-
return a + b
|
|
428
|
-
|
|
429
|
-
// Test for the function
|
|
430
|
-
test "add should sum two numbers":
|
|
431
|
-
result = add(2, 3)
|
|
432
|
-
expect result equals 5
|
|
433
|
-
```
|
|
434
|
-
|
|
435
|
-
## Test Structure
|
|
436
|
-
|
|
437
|
-
Every test has three parts:
|
|
438
|
-
|
|
439
|
-
1. **Setup** - Prepare what you need
|
|
440
|
-
2. **Execute** - Run the code
|
|
441
|
-
3. **Verify** - Check the result
|
|
442
|
-
|
|
443
|
-
```pseudocode
|
|
444
|
-
test "should create user with name":
|
|
445
|
-
// 1. Setup
|
|
446
|
-
userName = "Alice"
|
|
447
|
-
|
|
448
|
-
// 2. Execute
|
|
449
|
-
user = createUser(userName)
|
|
450
|
-
|
|
451
|
-
// 3. Verify
|
|
452
|
-
expect user.name equals "Alice"
|
|
453
|
-
```
|
|
454
|
-
|
|
455
|
-
## Common Assertions
|
|
456
|
-
|
|
457
|
-
```pseudocode
|
|
458
|
-
// Equality
|
|
459
|
-
expect value equals 5
|
|
460
|
-
expect value equals { id: 1 }
|
|
461
|
-
|
|
462
|
-
// Truthiness
|
|
463
|
-
expect value is truthy
|
|
464
|
-
expect value is falsy
|
|
465
|
-
expect value is null
|
|
466
|
-
expect value is undefined
|
|
467
|
-
|
|
468
|
-
// Numbers
|
|
469
|
-
expect value > 3
|
|
470
|
-
expect value < 10
|
|
471
|
-
|
|
472
|
-
// Strings
|
|
473
|
-
expect text contains "hello"
|
|
474
|
-
|
|
475
|
-
// Arrays/Lists
|
|
476
|
-
expect array contains item
|
|
477
|
-
expect array length equals 3
|
|
478
|
-
```
|
|
479
|
-
|
|
480
|
-
## Testing Expected Errors
|
|
481
|
-
|
|
482
|
-
```pseudocode
|
|
483
|
-
test "should throw error for invalid input":
|
|
484
|
-
expect error when:
|
|
485
|
-
divide(10, 0)
|
|
486
|
-
with message "Cannot divide by zero"
|
|
487
|
-
```
|
|
488
|
-
|
|
489
|
-
## Async Tests
|
|
490
|
-
|
|
491
|
-
```pseudocode
|
|
492
|
-
test "should fetch user data" async:
|
|
493
|
-
user = await fetchUser(123)
|
|
494
|
-
expect user.id equals 123
|
|
495
|
-
```
|
|
496
|
-
|
|
497
|
-
## Test Naming
|
|
498
|
-
|
|
499
|
-
Use clear, descriptive names:
|
|
500
|
-
|
|
501
|
-
```pseudocode
|
|
502
|
-
// ❌ Bad
|
|
503
|
-
test "test1"
|
|
504
|
-
test "it works"
|
|
505
|
-
|
|
506
|
-
// ✅ Good
|
|
507
|
-
test "should return user when ID exists"
|
|
508
|
-
test "should throw error when ID is invalid"
|
|
509
|
-
```
|
|
510
|
-
|
|
511
|
-
## Running Tests
|
|
512
|
-
|
|
513
|
-
```bash
|
|
514
|
-
# Run all tests
|
|
515
|
-
run-tests
|
|
516
|
-
|
|
517
|
-
# Run specific test file
|
|
518
|
-
run-tests user-test
|
|
519
|
-
|
|
520
|
-
# Watch mode (re-run on changes)
|
|
521
|
-
run-tests --watch
|
|
522
|
-
```
|
|
523
|
-
|
|
524
|
-
## Best Practices
|
|
525
|
-
|
|
526
|
-
1. **One test, one thing** - Test one behavior per test
|
|
527
|
-
2. **Independent tests** - Tests should not depend on each other
|
|
528
|
-
3. **Clear names** - Name should describe what is being tested
|
|
529
|
-
4. **Fast tests** - Tests should run quickly
|
|
530
|
-
|
|
531
|
-
```pseudocode
|
|
532
|
-
// ❌ Bad: Testing multiple things
|
|
533
|
-
test "user operations":
|
|
534
|
-
expect createUser("Bob").name equals "Bob"
|
|
535
|
-
expect deleteUser(1) equals true
|
|
536
|
-
expect listUsers().length equals 0
|
|
537
|
-
|
|
538
|
-
// ✅ Good: One test per operation
|
|
539
|
-
test "should create user with given name":
|
|
540
|
-
user = createUser("Bob")
|
|
541
|
-
expect user.name equals "Bob"
|
|
542
|
-
|
|
543
|
-
test "should delete user by ID":
|
|
544
|
-
result = deleteUser(1)
|
|
545
|
-
expect result equals true
|
|
546
|
-
|
|
547
|
-
test "should return empty list when no users":
|
|
548
|
-
users = listUsers()
|
|
549
|
-
expect users.length equals 0
|
|
550
|
-
```
|
|
551
|
-
|
|
552
|
-
## When to Write Tests
|
|
553
|
-
|
|
554
|
-
- **Before fixing bugs** - Write test that fails, then fix
|
|
555
|
-
- **For new features** - Test expected behavior
|
|
556
|
-
- **For edge cases** - Empty input, null values, large numbers
|
|
557
|
-
|
|
558
|
-
## What to Test
|
|
559
|
-
|
|
560
|
-
✅ **Do test:**
|
|
561
|
-
- Public functions and methods
|
|
562
|
-
- Edge cases (empty, null, zero, negative)
|
|
563
|
-
- Error conditions
|
|
564
|
-
|
|
565
|
-
❌ **Don't test:**
|
|
566
|
-
- Private implementation details
|
|
567
|
-
- Third-party libraries (they're already tested)
|
|
568
|
-
- Getters/setters with no logic
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
---
|
|
572
|
-
*Generated by aicgen*
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Add or update comprehensive documentation for code
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
* Analyze the selected code for documentation needs
|
|
6
|
-
* Add inline documentation with clear descriptions
|
|
7
|
-
* Include parameter types and return value documentation
|
|
8
|
-
* Add usage examples for complex functions
|
|
9
|
-
* Follow language-specific documentation standards
|
|
10
|
-
* Update README.md if adding new features
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Generate integration tests for API endpoints and system components
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
* Identify integration points (APIs, databases, services)
|
|
6
|
-
* Create integration test files
|
|
7
|
-
* Test end-to-end workflows
|
|
8
|
-
* Use realistic test data and fixtures
|
|
9
|
-
* Include proper setup and teardown
|
|
10
|
-
* Ensure tests are idempotent
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Generate comprehensive unit tests for all functions and methods
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
* Analyze the selected file or directory for testable code
|
|
6
|
-
* Generate test files with appropriate naming conventions
|
|
7
|
-
* Create test cases covering happy path, edge cases, and error handling
|
|
8
|
-
* Mock external dependencies appropriately
|
|
9
|
-
* Follow language-specific testing best practices
|
|
10
|
-
* Aim for >80% code coverage
|
|
11
|
-
* Include setup and teardown methods where needed
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Analyze code for performance bottlenecks and optimization opportunities
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
* Profile code to identify hotspots
|
|
6
|
-
* Check for N+1 queries and inefficient algorithms
|
|
7
|
-
* Analyze caching opportunities
|
|
8
|
-
* Review resource management
|
|
9
|
-
* Suggest specific optimizations
|
|
10
|
-
* Estimate performance impact
|
|
11
|
-
* Prioritize recommendations
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Extract code into a separate, reusable module
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
* Identify the code section to extract
|
|
6
|
-
* Analyze dependencies and determine module interface
|
|
7
|
-
* Create a new module file following project conventions
|
|
8
|
-
* Maintain original functionality and behavior
|
|
9
|
-
* Update imports and exports appropriately
|
|
10
|
-
* Ensure no circular dependencies
|
|
11
|
-
* Add documentation to the new module
|
|
12
|
-
* Verify all tests still pass
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Perform comprehensive security audit of the codebase
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
* Scan for common vulnerabilities (SQL injection, XSS, etc.)
|
|
6
|
-
* Check authentication and authorization logic
|
|
7
|
-
* Review input validation and sanitization
|
|
8
|
-
* Examine error handling for information leakage
|
|
9
|
-
* Verify secure handling of sensitive data
|
|
10
|
-
* Check third-party dependencies
|
|
11
|
-
* Suggest remediation steps
|
|
12
|
-
* Prioritize findings by severity
|