Generate comprehensive tests (unit, integration, E2E) from descriptions or source code. Supports Vitest, Jest, and Playwright. Includes mocking, assertions, and coverage configuration. Use when writing tests for functions, APIs, or user flows.
Generate production-ready tests from natural language descriptions or source code using AI.
This skill transforms descriptions or source code into comprehensive test suites with:
python3 scripts/generate_tests.py "Tests for user authentication functions"
python3 scripts/generate_tests.py --file src/utils/format.ts
python3 scripts/generate_tests.py "E2E tests for checkout flow" --type e2e --framework playwright
python3 scripts/generate_tests.py --config --framework vitest
Unit Tests - Test individual functions/methods:
"Tests for calculateTotal function with tax and discounts"
Integration Tests - Test multiple components:
"Integration tests for user registration API endpoint"
E2E Tests - Test complete user flows:
"E2E tests for login, browse products, and checkout flow"
Run the generator:
python3 scripts/generate_tests.py "<description>" [options]
Options:
--type unit - Unit tests (default)--type integration - Integration tests--type e2e - E2E tests--framework vitest - Vitest (default for unit/integration)--framework jest - Jest--framework playwright - Playwright (for E2E)--file <path> - Generate tests for source file--output-file <path> - Output test file path--coverage - Include coverage configuration--config - Generate test configuration filevitest run
# or
npm test
Description:
"Tests for formatCurrency function that formats numbers as currency"
Command:
python3 scripts/generate_tests.py "Tests for formatCurrency function" --output-file utils/format.test.ts
Generated (excerpt):
import { describe, it, expect } from 'vitest';
import { formatCurrency } from './format';
describe('formatCurrency', () => {
it('should format positive numbers correctly', () => {
expect(formatCurrency(1234.56)).toBe('$1,234.56');
});
it('should handle zero', () => {
expect(formatCurrency(0)).toBe('$0.00');
});
it('should handle negative numbers', () => {
expect(formatCurrency(-100)).toBe('-$100.00');
});
it('should round to 2 decimal places', () => {
expect(formatCurrency(10.999)).toBe('$11.00');
});
});
Source File (src/utils/validate.ts):
export function validateEmail(email: string): boolean {
const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return regex.test(email);
}
Command:
python3 scripts/generate_tests.py --file src/utils/validate.ts
Generated:
import { describe, it, expect } from 'vitest';
import { validateEmail } from './validate';
describe('validateEmail', () => {
it('should accept valid email', () => {
expect(validateEmail('user@example.com')).toBe(true);
});
it('should reject email without @', () => {
expect(validateEmail('userexample.com')).toBe(false);
});
it('should reject email without domain', () => {
expect(validateEmail('user@')).toBe(false);
});
it('should reject empty string', () => {
expect(validateEmail('')).toBe(false);
});
});
Description:
"Integration tests for POST /api/posts endpoint with authentication and validation"
Command:
python3 scripts/generate_tests.py "Integration tests for POST /api/posts" --type integration
Generated (excerpt):
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
import request from 'supertest';
import { app } from '../app';
describe('POST /api/posts', () => {
let authToken: string;
beforeAll(async () => {
authToken = await createTestUser();
});
afterAll(async () => {
await cleanupTestData();
});
it('should create post with valid data', async () => {
const response = await request(app)
.post('/api/posts')
.set('Authorization', `Bearer ${authToken}`)
.send({
title: 'Test Post',
content: 'Test content',
});
expect(response.status).toBe(201);
expect(response.body).toMatchObject({
title: 'Test Post',
content: 'Test content',
});
});
it('should return 401 without authentication', async () => {
const response = await request(app)
.post('/api/posts')
.send({ title: 'Test', content: 'Test' });
expect(response.status).toBe(401);
});
});
Description:
"E2E tests for complete checkout flow: login, add to cart, checkout, payment"
Command:
python3 scripts/generate_tests.py "E2E checkout flow" --type e2e --framework playwright
Generated (excerpt):
import { test, expect } from '@playwright/test';
test('complete checkout flow', async ({ page }) => {
// Login
await page.goto('/login');
await page.fill('input[name="email"]', 'user@example.com');
await page.fill('input[name="password"]', 'password');
await page.click('button[type="submit"]');
// Browse and add to cart
await page.goto('/products');
await page.click('.product:first-child .add-to-cart');
await expect(page.locator('.cart-badge')).toContainText('1');
// Checkout
await page.click('.cart-icon');
await page.click('button:has-text("Checkout")');
// Payment
await page.fill('input[name="cardNumber"]', '4242424242424242');
await page.click('button:has-text("Pay")');
// Verify success
await expect(page.locator('.success-message')).toBeVisible();
});
Best for: Individual functions, utilities, business logic
Pros:
Cons:
Example:
it('should calculate discount', () => {
expect(calculateDiscount(100, 0.1)).toBe(90);
});
Best for: API endpoints, database operations, multiple components
Pros:
Cons:
Example:
it('should create user in database', async () => {
const user = await createUser({ email: 'test@example.com' });
expect(user.id).toBeDefined();
});
Best for: Critical user journeys, complete workflows
Pros:
Cons:
Example:
test('user can complete purchase', async ({ page }) => {
await page.goto('/products');
await page.click('.buy-button');
await expect(page).toHaveURL('/success');
});
Best for: Modern TypeScript projects, Vite-based apps
Pros:
Cons:
Best for: React projects, established codebases
Pros:
Cons:
Best for: E2E testing, cross-browser testing
Pros:
Cons:
Arrange, Act, Assert - The foundation of good tests:
it('should add items to cart', () => {
// Arrange - Setup
const cart = new Cart();
const item = { id: '1', price: 10 };
// Act - Execute
cart.add(item);
// Assert - Verify
expect(cart.items).toHaveLength(1);
expect(cart.total).toBe(10);
});
Mock external dependencies:
// Mock function
const mockFn = vi.fn().mockReturnValue(42);
// Mock module
vi.mock('~/lib/db', () => ({
db: {
user: {
findMany: vi.fn(),
},
},
}));
// Use mock
await fetchUsers();
expect(db.user.findMany).toHaveBeenCalled();
Run code before/after tests:
describe('UserService', () => {
let service: UserService;
beforeEach(() => {
service = new UserService();
});
afterEach(() => {
vi.clearAllMocks();
});
it('should create user', () => {
// Test uses fresh service
});
});
Use templates/vitest_unit.test.ts for unit test patterns:
Use templates/playwright_e2e.test.ts for E2E patterns:
The generator follows these best practices automatically:
// ✅ Good
it('should return null when user is not found')
// ❌ Bad
it('works')
// Test happy path
it('should accept valid input', () => {});
// Test edge cases
it('should handle empty string', () => {});
it('should handle negative numbers', () => {});
it('should handle null', () => {});
// Mock API calls
vi.mock('~/lib/api');
// Mock database
vi.mock('~/lib/db');
// ✅ Good - Each test is independent
it('test 1', () => {
const data = createTestData();
// Use data
});
it('test 2', () => {
const data = createTestData();
// Use data
});
// ❌ Bad - Tests depend on each other
let sharedData;
it('test 1', () => {
sharedData = createTestData();
});
it('test 2', () => {
// Uses sharedData from test 1
});
// ✅ Specific assertions
expect(user.email).toBe('user@example.com');
expect(users).toHaveLength(5);
// ❌ Vague assertions
expect(user).toBeTruthy();
expect(users.length > 0).toBe(true);
python3 scripts/generate_tests.py --config --framework vitest
Generated (vitest.config.ts):
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
globals: true,
environment: 'node',
coverage: {
provider: 'v8',
reporter: ['text', 'json', 'html'],
},
},
});
python3 scripts/generate_tests.py --config --framework playwright
Generated (playwright.config.ts):
import { defineConfig } from '@playwright/test';
export default defineConfig({
testDir: './tests/e2e',
use: {
baseURL: 'http://localhost:3000',
},
webServer: {
command: 'npm run dev',
url: 'http://localhost:3000',
},
});
# Vitest
vitest --coverage
# Jest
jest --coverage
High Priority (aim for 100%):
Medium Priority (aim for 80%):
Low Priority (can skip):
Solution: Ensure test framework is installed:
npm install -D vitest
# or
npm install -D jest
# or
npm install -D @playwright/test
Solution: Check mock syntax for your framework:
// Vitest
vi.mock('module');
// Jest
jest.mock('module');
Solution: Ensure dev server is running:
npm run dev
Or configure webServer in Playwright config.
describe.each([
{ input: 1, expected: 2 },
{ input: 2, expected: 4 },
{ input: 3, expected: 6 },
])('double($input)', ({ input, expected }) => {
it(`should return ${expected}`, () => {
expect(double(input)).toBe(expected);
});
});
it('should match snapshot', () => {
const data = generateComplexData();
expect(data).toMatchSnapshot();
});
expect.extend({
toBeValidEmail(received) {
const pass = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(received);
return {
pass,
message: () => `Expected ${received} to be a valid email`,
};
},
});
expect('user@example.com').toBeValidEmail();
references/testing_patterns.md - Testing patterns and best practicestemplates/vitest_unit.test.ts - Vitest unit test templatetemplates/playwright_e2e.test.ts - Playwright E2E test template✅ Tests generate without errors
✅ Tests compile and run
✅ Tests cover happy paths and edge cases
✅ Mocks work correctly
✅ Assertions are specific and clear
✅ Tests are independent
✅ Coverage meets goals (80%+)
After generating your tests:
Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer