322 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			322 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| # Документация по тестированию 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) |