Writing Unit Tests with AI
AI is exceptionally good at generating tests. It can enumerate edge cases faster than most developers and write the boilerplate quickly. Your job is to verify the tests actually catch real bugs.
Generate tests from an implementation
Paste the function and ask for tests:
Write unit tests for this function using Vitest.
Cover: the happy path, empty input, null/undefined input,
boundary values, and any edge cases you can identify.
[paste function]
Generate tests from a specification
If you're doing TDD, describe the expected behaviour before writing code:
Write tests for a function called `calculateDiscount(price, coupon)` that:
- Returns the price with 10% off if coupon is "SAVE10"
- Returns the price with 20% off if coupon is "SAVE20"
- Returns the original price if coupon is null or unrecognised
- Throws if price is negative
Use Vitest. Don't implement the function, just the tests.
Identify missing test cases
Paste your existing tests and ask what's missing:
Here are my current tests for the auth middleware:
[paste tests]
What cases am I not covering? List them without writing code yet.
Then ask it to write the missing ones after you've reviewed the list.
Generate mock data and fixtures
Generate 5 realistic mock User objects for testing. They should cover:
- A regular user
- An admin user
- A user with a very long name (boundary test)
- A user with special characters in their email
- A deactivated user (isActive: false)
Use this TypeScript type: [paste type]
Snapshot and integration tests
AI can also help with more complex test types:
Write an integration test for the POST /api/users endpoint using
supertest and Vitest. It should:
1. Create a user with valid data → expect 201 with the created user
2. Submit invalid data → expect 422 with a validation error
3. Submit a duplicate email → expect 409 with a conflict error
The Express app is exported from src/app.ts.
Reviewing generated tests
Before committing AI-generated tests, verify:
- Each test actually fails when the implementation is wrong
- Mocks reflect real behaviour (not just return
undefinedeverywhere) - Test descriptions are accurate and readable
- There are no tests that always pass regardless of implementation