Тесты: часть 1
This commit is contained in:
322
tests/README.md
Normal file
322
tests/README.md
Normal file
@@ -0,0 +1,322 @@
|
||||
# Документация по тестированию API CodeGen
|
||||
|
||||
## Обзор
|
||||
|
||||
Проект использует комплексную систему тестирования с максимальным покрытием:
|
||||
- **Юнит тесты** - тестирование отдельных модулей
|
||||
- **Интеграционные тесты** - тестирование взаимодействия компонентов
|
||||
- **E2E тесты** - полный цикл от генерации до использования
|
||||
|
||||
**Общее количество тестов:** ~72 кейса
|
||||
|
||||
## Стек технологий
|
||||
|
||||
- **Bun test** - встроенный test runner (быстрый, совместим с Jest API)
|
||||
- **msw** - Mock Service Worker для HTTP мокирования
|
||||
- **tmp** - создание временных директорий
|
||||
- **execa** - запуск CLI команд
|
||||
|
||||
## Структура тестов
|
||||
|
||||
```
|
||||
tests/
|
||||
├── fixtures/ # Тестовые OpenAPI спецификации
|
||||
│ ├── minimal.json # Минимальная валидная спецификация
|
||||
│ ├── valid.json # Полная валидная спецификация
|
||||
│ ├── complex.json # Сложная (100+ endpoints)
|
||||
│ ├── with-auth.json # С authentication
|
||||
│ ├── invalid.json # Невалидная спецификация
|
||||
│ ├── empty.json # Пустая спецификация
|
||||
│ └── edge-cases.json # Unicode, спецсимволы
|
||||
│
|
||||
├── helpers/ # Вспомогательные функции
|
||||
│ ├── setup.ts # Создание/очистка temp директорий
|
||||
│ ├── mock-server.ts # Mock HTTP сервер
|
||||
│ └── fixtures.ts # Утилиты для фикстур
|
||||
│
|
||||
├── unit/ # Юнит тесты
|
||||
│ ├── cli.test.ts # CLI команды
|
||||
│ ├── generator.test.ts # Генератор
|
||||
│ ├── config.test.ts # Валидация конфигурации
|
||||
│ └── utils/
|
||||
│ └── file.test.ts # Файловые утилиты
|
||||
│
|
||||
└── integration/ # Интеграционные тесты
|
||||
├── e2e-generation.test.ts # E2E генерация
|
||||
└── generated-client.test.ts # Сгенерированный клиент
|
||||
```
|
||||
|
||||
## Запуск тестов
|
||||
|
||||
### Все тесты
|
||||
```bash
|
||||
bun test
|
||||
```
|
||||
|
||||
### Только юнит тесты
|
||||
```bash
|
||||
bun test:unit
|
||||
```
|
||||
|
||||
### Только интеграционные тесты
|
||||
```bash
|
||||
bun test:integration
|
||||
```
|
||||
|
||||
### Watch режим
|
||||
```bash
|
||||
bun test:watch
|
||||
```
|
||||
|
||||
### С coverage
|
||||
```bash
|
||||
bun test:coverage
|
||||
```
|
||||
|
||||
### Конкретный файл
|
||||
```bash
|
||||
bun test tests/unit/cli.test.ts
|
||||
```
|
||||
|
||||
### Конкретный тест
|
||||
```bash
|
||||
bun test -t "should generate client with custom name"
|
||||
```
|
||||
|
||||
## Покрываемые сценарии
|
||||
|
||||
### 1. CLI тесты (15 кейсов)
|
||||
|
||||
**Базовые сценарии:**
|
||||
- ✅ Запуск с локальным файлом
|
||||
- ✅ Запуск с URL
|
||||
- ✅ Генерация с кастомным именем
|
||||
- ✅ Автоматическое имя из OpenAPI title
|
||||
- ✅ Отображение версии `--version`
|
||||
- ✅ Отображение help `--help`
|
||||
|
||||
**Обработка ошибок:**
|
||||
- ❌ Отсутствие `--input`
|
||||
- ❌ Отсутствие `--output`
|
||||
- ❌ Несуществующий файл
|
||||
- ❌ Невалидный OpenAPI
|
||||
- ❌ Недоступный URL
|
||||
- ❌ Ошибки записи
|
||||
|
||||
### 2. Генератор (20 кейсов)
|
||||
|
||||
**Корректная генерация:**
|
||||
- ✅ Создание файла
|
||||
- ✅ Структура кода
|
||||
- ✅ Все HTTP методы (GET, POST, PUT, PATCH, DELETE)
|
||||
- ✅ Типы для request/response
|
||||
- ✅ Path/query параметры
|
||||
- ✅ Request body
|
||||
- ✅ Enum типы
|
||||
- ✅ Bearer authentication
|
||||
- ✅ Хук `onFormatRouteName`
|
||||
- ✅ BaseUrl из servers
|
||||
|
||||
**Edge cases:**
|
||||
- ❌ Пустая спецификация
|
||||
- ❌ Минимальная спецификация
|
||||
- ❌ Сложная спецификация (100+ endpoints)
|
||||
- ❌ Unicode символы
|
||||
|
||||
### 3. Утилиты (10 кейсов)
|
||||
|
||||
**file.test.ts:**
|
||||
- ✅ `fileExists()` - существующий файл
|
||||
- ✅ `fileExists()` - несуществующий файл
|
||||
- ✅ `readJsonFile()` - локальный файл
|
||||
- ✅ `readJsonFile()` - URL
|
||||
- ❌ `readJsonFile()` - невалидный JSON
|
||||
- ❌ `readJsonFile()` - недоступный URL
|
||||
- ✅ `ensureDir()` - создание директорий
|
||||
- ✅ `writeFileWithDirs()` - запись с созданием директорий
|
||||
|
||||
**config.test.ts:**
|
||||
- ✅ Валидная конфигурация
|
||||
- ❌ Без inputPath
|
||||
- ❌ Без outputPath
|
||||
- ✅ Опциональное поле fileName
|
||||
|
||||
### 4. Сгенерированный клиент (7 кейсов)
|
||||
|
||||
**Компиляция:**
|
||||
- ✅ TypeScript компиляция без ошибок
|
||||
- ✅ Отсутствие type errors
|
||||
- ✅ Корректные импорты/экспорты
|
||||
|
||||
**Корректность API:**
|
||||
- ✅ Все endpoints присутствуют
|
||||
- ✅ Корректные имена методов
|
||||
- ✅ HttpClient инициализация
|
||||
- ✅ Метод `setSecurityData`
|
||||
|
||||
### 5. Интеграционные E2E (15 кейсов)
|
||||
|
||||
**Полный цикл:**
|
||||
- ✅ CLI → создание → импорт → использование
|
||||
- ✅ Генерация из локального файла
|
||||
- ✅ Генерация из URL
|
||||
- ✅ Повторная генерация
|
||||
|
||||
**HTTP с mock:**
|
||||
- ✅ GET без параметров
|
||||
- ✅ GET с query параметрами
|
||||
- ✅ POST с body
|
||||
- ✅ PUT/PATCH/DELETE
|
||||
- ✅ Статусы 200, 201, 400, 401, 404, 500
|
||||
- ❌ Network errors
|
||||
- ✅ Bearer authentication
|
||||
- ✅ Custom headers
|
||||
|
||||
## Написание новых тестов
|
||||
|
||||
### Пример юнит теста
|
||||
|
||||
```typescript
|
||||
import { describe, test, expect, beforeEach, afterEach } from 'bun:test';
|
||||
import { setupTest } from '../helpers/setup.js';
|
||||
|
||||
describe('My Feature', () => {
|
||||
let tempDir: string;
|
||||
let cleanup: () => Promise<void>;
|
||||
|
||||
beforeEach(async () => {
|
||||
const setup = await setupTest();
|
||||
tempDir = setup.tempDir;
|
||||
cleanup = setup.cleanup;
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await cleanup();
|
||||
});
|
||||
|
||||
test('should do something', () => {
|
||||
// Arrange
|
||||
const input = 'test';
|
||||
|
||||
// Act
|
||||
const result = myFunction(input);
|
||||
|
||||
// Assert
|
||||
expect(result).toBe('expected');
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### Пример интеграционного теста
|
||||
|
||||
```typescript
|
||||
import { describe, test, expect, beforeAll, afterAll } from 'bun:test';
|
||||
import { createMockServer } from '../helpers/mock-server.js';
|
||||
|
||||
describe('Integration Test', () => {
|
||||
let mockServer;
|
||||
|
||||
beforeAll(() => {
|
||||
mockServer = createMockServer();
|
||||
mockServer.start();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
mockServer.stop();
|
||||
});
|
||||
|
||||
test('should make HTTP request', async () => {
|
||||
const response = await fetch('https://api.example.com/users');
|
||||
const data = await response.json();
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(Array.isArray(data)).toBe(true);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
## Лучшие практики
|
||||
|
||||
### 1. Изоляция тестов
|
||||
- Каждый тест должен быть независимым
|
||||
- Использовать `beforeEach`/`afterEach` для setup/cleanup
|
||||
- Не полагаться на порядок выполнения
|
||||
|
||||
### 2. Именование
|
||||
- Описательные названия: `"должен создать файл при корректных параметрах"`
|
||||
- Группировать с помощью `describe`
|
||||
- Использовать принцип AAA (Arrange, Act, Assert)
|
||||
|
||||
### 3. Очистка ресурсов
|
||||
- Всегда очищать временные файлы
|
||||
- Закрывать соединения
|
||||
- Использовать `afterEach` для гарантии очистки
|
||||
|
||||
### 4. Async/Await
|
||||
- Всегда использовать `async/await` для асинхронных операций
|
||||
- Не забывать `await` перед промисами
|
||||
- Устанавливать таймауты для долгих операций
|
||||
|
||||
### 5. Mock данные
|
||||
- Использовать фикстуры для тестовых данных
|
||||
- Не хардкодить данные в тестах
|
||||
- Переиспользовать тестовые данные
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Тесты падают с timeout
|
||||
Увеличьте таймаут для конкретного теста:
|
||||
```typescript
|
||||
test('long running test', async () => {
|
||||
// test code
|
||||
}, 60000); // 60 секунд
|
||||
```
|
||||
|
||||
### Тесты не очищаются
|
||||
Проверьте что `cleanup()` вызывается в `afterEach`:
|
||||
```typescript
|
||||
afterEach(async () => {
|
||||
await cleanup();
|
||||
});
|
||||
```
|
||||
|
||||
### Mock сервер не работает
|
||||
Убедитесь что:
|
||||
1. Сервер запущен в `beforeAll`
|
||||
2. Сервер остановлен в `afterAll`
|
||||
3. Хендлеры правильно настроены
|
||||
|
||||
### Файлы не находятся
|
||||
Используйте абсолютные пути или пути относительно `__dirname`:
|
||||
```typescript
|
||||
const fixturePath = join(__dirname, '../fixtures/test.json');
|
||||
```
|
||||
|
||||
## CI/CD
|
||||
|
||||
Тесты автоматически запускаются при:
|
||||
- Push в любую ветку
|
||||
- Создании Pull Request
|
||||
- Перед деплоем
|
||||
|
||||
Требования для прохождения CI:
|
||||
- ✅ Все тесты должны пройти
|
||||
- ✅ Coverage > 80%
|
||||
- ✅ Нет TypeScript ошибок
|
||||
- ✅ Нет lint ошибок
|
||||
|
||||
## Метрики
|
||||
|
||||
### Целевые показатели
|
||||
- **Coverage:** > 90%
|
||||
- **Скорость:** < 30 сек для всех тестов
|
||||
- **Стабильность:** 0 flaky тестов
|
||||
|
||||
### Текущие показатели
|
||||
Запустите `bun test:coverage` для просмотра актуальных метрик.
|
||||
|
||||
## Дополнительная информация
|
||||
|
||||
- [План тестирования](../TESTING-PLAN.md)
|
||||
- [Contributing Guidelines](../CONTRIBUTING.md)
|
||||
- [Bun Test Documentation](https://bun.sh/docs/cli/test)
|
||||
Reference in New Issue
Block a user