| name | write-tests |
| description | Defines test standards. Must use before writing any test code. |
Write tests
Core principle: Tests should verify behavior through public interfaces, not implementation details. Code can change entirely; tests shouldn't.
Your work: Write requested tests with respect to the styles below.
Anti-Pattern: Test Before Logic
If you find the real logic has not been implemented but you are asked to write tests. Reject immediately and report back "Real implementation not found, refuse to write tests."
Testing Style
Good Tests
Integration-style: Test through real interfaces, not mocks of internal parts.
test('user can checkout with valid cart', async () => {
const cart = createCart();
cart.add(product);
const result = await checkout(cart, paymentMethod);
expect(result.status).toBe('confirmed');
});
Characteristics:
- Tests behavior users/callers care about
- Uses public API only
- Survives internal refactors
- Describes WHAT, not HOW
- One logical assertion per test
- Flat top-level
test() inside test files instead of nested describe() and it().
Bad Tests
Implementation-detail tests: Coupled to internal structure.
test('checkout calls paymentService.process', async () => {
const mockPayment = jest.mock(paymentService);
await checkout(cart, payment);
expect(mockPayment.process).toHaveBeenCalledWith(cart.total);
});
Red flags:
- Mocking internal collaborators
- Testing private methods
- Asserting on call counts/order
- Test breaks when refactoring without behavior change
- Test name describes HOW not WHAT
- Verifying through external means instead of interface
test('createUser saves to database', async () => {
await createUser({ name: 'Alice' });
const row = await db.query('SELECT * FROM users WHERE name = ?', ['Alice']);
expect(row).toBeDefined();
});
test('createUser makes user retrievable', async () => {
const user = await createUser({ name: 'Alice' });
const retrieved = await getUser(user.id);
expect(retrieved.name).toBe('Alice');
});
Mocking Style
Mock at system boundaries only:
- External APIs (payment, email, stub deps, etc. If it is a dependency package to be mocked, prefer mocking full interface in a central file instead of mocking in each file)
- Databases (sometimes - prefer test DB)
- Time/randomness
- File system (sometimes)
Don't mock:
- Your own classes/modules
- Internal collaborators
- Anything you control
Checklist When Finish