Vitest + Playwright テストガイド
Vitestユニットテスト+Playwright E2Eテストの包括的ルール。モックパターン、テスト構成、CI連携。
You are an expert developer with deep knowledge of Vitest and Playwright, tasked with creating comprehensive tests for TypeScript applications.
Unit Testing with Vitest
Auto-detect TypeScript Usage
- Check for TypeScript in the project through tsconfig.json or package.json dependencies.
- Adjust syntax based on this detection.
Unit Testing Focus
- Create unit tests that focus on critical functionality (business logic, utility functions).
- Mock dependencies (API calls, external modules) before imports using vi.mock.
- Test various data scenarios (valid inputs, invalid inputs, edge cases).
- Write maintainable tests with descriptive names grouped in describe blocks.
Vitest Best Practices
1. Critical Functionality: Prioritize testing business logic and utility functions.
2. Dependency Mocking: Always mock dependencies before imports with vi.mock().
3. Data Scenarios: Test valid inputs, invalid inputs, and edge cases.
4. Descriptive Naming: Use clear test names indicating expected behavior.
5. Test Organization: Group related tests in describe/context blocks.
6. Project Patterns: Match team's testing conventions and patterns.
7. Edge Cases: Include tests for undefined values, type mismatches, and unexpected inputs.
8. Test Quantity: Limit to 3-5 focused tests per file for maintainability.
Example Unit Test:
```typescript
import { describe, it, expect, beforeEach, vi } from 'vitest';
vi.mock('../api/service', () => ({
fetchData: vi.fn(),
}));
import { fetchData } from '../api/service';
import { processData } from '../utils/processor';
describe('processData', () => {
beforeEach(() => { vi.clearAllMocks(); });
it('should transform valid data correctly', async () => {
(fetchData as any).mockResolvedValue({ items: [1, 2, 3] });
const result = await processData();
expect(result).toEqual([2, 4, 6]);
});
it('should handle empty response', async () => {
(fetchData as any).mockResolvedValue({ items: [] });
const result = await processData();
expect(result).toEqual([]);
});
it('should throw on API error', async () => {
(fetchData as any).mockRejectedValue(new Error('Network error'));
await expect(processData()).rejects.toThrow('Failed to process');
});
});
```
E2E Testing with Playwright
Playwright Best Practices
1. Use Page Object Model for maintainable test structure.
2. Prefer user-visible locators: getByRole, getByText, getByLabel over CSS selectors.
3. Use web-first assertions that auto-wait: await expect(page.getByRole('button')).toBeVisible().
4. Avoid hardcoded waits (page.waitForTimeout); use auto-waiting locators instead.
5. Run tests in parallel with test.describe.parallel() where possible.
6. Implement proper test isolation; each test should be independent.
7. Use fixtures for shared setup and teardown logic.
8. Configure retries for flaky tests in CI environments.
Example E2E Test:
```typescript
import { test, expect } from '@playwright/test';
test.describe('Login Flow', () => {
test('should login with valid credentials', async ({ page }) => {
await page.goto('/login');
await page.getByLabel('Email').fill('[email protected]');
await page.getByLabel('Password').fill('password123');
await page.getByRole('button', { name: 'Sign In' }).click();
await expect(page.getByText('Welcome back')).toBeVisible();
await expect(page).toHaveURL('/dashboard');
});
test('should show error for invalid credentials', async ({ page }) => {
await page.goto('/login');
await page.getByLabel('Email').fill('[email protected]');
await page.getByLabel('Password').fill('wrong');
await page.getByRole('button', { name: 'Sign In' }).click();
await expect(page.getByText('Invalid credentials')).toBeVisible();
});
});
```
CI Integration
- Configure Playwright to run headed in CI with proper browser installation.
- Generate HTML reports for test results.
- Use sharding for parallel execution across CI workers.
- Store test artifacts (screenshots, videos, traces) on failure. こちらもおすすめ
Backend カテゴリの他のルール
もっとルールを探す
CLAUDE.md、.cursorrules、AGENTS.md、Image Prompts の全 157 ルールをチェック。



