393 lines
17 KiB
Markdown
393 lines
17 KiB
Markdown
|
|
# План реализации тестирования API CodeGen
|
|||
|
|
|
|||
|
|
## Общая информация
|
|||
|
|
|
|||
|
|
**Цель:** Максимальное покрытие тестами CLI инструмента и сгенерированного клиента
|
|||
|
|
|
|||
|
|
**Итого тестовых кейсов:** ~72
|
|||
|
|
|
|||
|
|
**Запуск:** `bun test` (одна команда)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Технологический стек
|
|||
|
|
|
|||
|
|
### Основные инструменты
|
|||
|
|
- [x] **Bun test** - встроенный test runner (быстрый, совместим с Jest API)
|
|||
|
|
- [ ] **msw** `^2.0.0` - Mock Service Worker для HTTP мокирования
|
|||
|
|
- [ ] **tmp** `^0.2.1` - создание временных директорий для тестов
|
|||
|
|
- [ ] **@types/tmp** `^0.2.6` - типы для tmp
|
|||
|
|
- [ ] **execa** `^8.0.0` - запуск CLI команд в тестах
|
|||
|
|
|
|||
|
|
### Преимущества выбранного стека
|
|||
|
|
- ✅ Быстрое выполнение тестов (Bun)
|
|||
|
|
- ✅ Реалистичное HTTP мокирование (msw)
|
|||
|
|
- ✅ Изолированное тестовое окружение (tmp)
|
|||
|
|
- ✅ Удобное тестирование CLI (execa)
|
|||
|
|
- ✅ Совместимость с Jest API (легкая миграция при необходимости)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Структура проекта с тестами
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
api-codegen/
|
|||
|
|
├── tests/
|
|||
|
|
│ ├── fixtures/ # Тестовые OpenAPI спецификации
|
|||
|
|
│ │ ├── minimal.json # Минимальная валидная спецификация
|
|||
|
|
│ │ ├── valid.json # Полная валидная спецификация
|
|||
|
|
│ │ ├── complex.json # Сложная (100+ endpoints)
|
|||
|
|
│ │ ├── invalid.json # Невалидная спецификация
|
|||
|
|
│ │ ├── with-auth.json # С authentication схемами
|
|||
|
|
│ │ ├── edge-cases.json # Unicode, спецсимволы
|
|||
|
|
│ │ └── empty.json # Пустая спецификация
|
|||
|
|
│ │
|
|||
|
|
│ ├── unit/ # Юнит тесты
|
|||
|
|
│ │ ├── cli.test.ts # Тесты CLI команд
|
|||
|
|
│ │ ├── generator.test.ts # Тесты генератора
|
|||
|
|
│ │ ├── config.test.ts # Тесты валидации конфигурации
|
|||
|
|
│ │ └── utils/
|
|||
|
|
│ │ └── file.test.ts # Тесты файловых утилит
|
|||
|
|
│ │
|
|||
|
|
│ ├── integration/ # Интеграционные тесты
|
|||
|
|
│ │ ├── e2e-generation.test.ts # End-to-end генерация
|
|||
|
|
│ │ └── generated-client.test.ts # Тесты сгенерированного клиента
|
|||
|
|
│ │
|
|||
|
|
│ └── helpers/ # Вспомогательные функции
|
|||
|
|
│ ├── setup.ts # Настройка окружения
|
|||
|
|
│ ├── mock-server.ts # Mock HTTP сервер (msw)
|
|||
|
|
│ └── fixtures.ts # Утилиты для работы с фикстурами
|
|||
|
|
│
|
|||
|
|
└── package.json
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Этапы реализации
|
|||
|
|
|
|||
|
|
### Этап 1: Подготовка инфраструктуры
|
|||
|
|
|
|||
|
|
#### 1.1. Установка зависимостей
|
|||
|
|
- [ ] Добавить `msw` в devDependencies
|
|||
|
|
- [ ] Добавить `tmp` и `@types/tmp` в devDependencies
|
|||
|
|
- [ ] Добавить `execa` в devDependencies
|
|||
|
|
- [ ] Выполнить `bun install`
|
|||
|
|
|
|||
|
|
#### 1.2. Создание структуры директорий
|
|||
|
|
- [ ] Создать `tests/`
|
|||
|
|
- [ ] Создать `tests/fixtures/`
|
|||
|
|
- [ ] Создать `tests/unit/`
|
|||
|
|
- [ ] Создать `tests/unit/utils/`
|
|||
|
|
- [ ] Создать `tests/integration/`
|
|||
|
|
- [ ] Создать `tests/helpers/`
|
|||
|
|
|
|||
|
|
#### 1.3. Настройка package.json
|
|||
|
|
- [ ] Добавить скрипт `"test": "bun test"`
|
|||
|
|
- [ ] Добавить скрипт `"test:unit": "bun test tests/unit"`
|
|||
|
|
- [ ] Добавить скрипт `"test:integration": "bun test tests/integration"`
|
|||
|
|
- [ ] Добавить скрипт `"test:watch": "bun test --watch"`
|
|||
|
|
- [ ] Добавить скрипт `"test:coverage": "bun test --coverage"`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### Этап 2: Создание тестовых фикстур
|
|||
|
|
|
|||
|
|
#### 2.1. minimal.json - минимальная спецификация
|
|||
|
|
- [ ] Базовая структура OpenAPI 3.0
|
|||
|
|
- [ ] Один GET endpoint
|
|||
|
|
- [ ] Минимальная info секция
|
|||
|
|
- [ ] Без servers
|
|||
|
|
- [ ] Простой response
|
|||
|
|
|
|||
|
|
#### 2.2. valid.json - полная валидная спецификация
|
|||
|
|
- [ ] Все основные HTTP методы (GET, POST, PUT, PATCH, DELETE)
|
|||
|
|
- [ ] Path параметры
|
|||
|
|
- [ ] Query параметры
|
|||
|
|
- [ ] Request body (JSON)
|
|||
|
|
- [ ] Response schemas
|
|||
|
|
- [ ] Базовые типы данных
|
|||
|
|
- [ ] Описания и примеры
|
|||
|
|
- [ ] Servers с baseUrl
|
|||
|
|
|
|||
|
|
#### 2.3. complex.json - сложная спецификация
|
|||
|
|
- [ ] 100+ endpoints
|
|||
|
|
- [ ] Вложенные объекты
|
|||
|
|
- [ ] Массивы объектов
|
|||
|
|
- [ ] Enum типы
|
|||
|
|
- [ ] Референсы ($ref)
|
|||
|
|
- [ ] Множественные tags
|
|||
|
|
- [ ] Различные content types
|
|||
|
|
|
|||
|
|
#### 2.4. with-auth.json - с аутентификацией
|
|||
|
|
- [ ] Bearer token authentication
|
|||
|
|
- [ ] API Key authentication
|
|||
|
|
- [ ] Security schemes
|
|||
|
|
- [ ] Защищенные endpoints
|
|||
|
|
|
|||
|
|
#### 2.5. edge-cases.json - edge cases
|
|||
|
|
- [ ] Unicode символы в названиях
|
|||
|
|
- [ ] Специальные символы в путях
|
|||
|
|
- [ ] Очень длинные названия
|
|||
|
|
- [ ] Зарезервированные слова
|
|||
|
|
- [ ] Нестандартные HTTP методы
|
|||
|
|
|
|||
|
|
#### 2.6. invalid.json - невалидная спецификация
|
|||
|
|
- [ ] Отсутствующие обязательные поля
|
|||
|
|
- [ ] Неправильная структура
|
|||
|
|
- [ ] Невалидные типы данных
|
|||
|
|
|
|||
|
|
#### 2.7. empty.json - пустая спецификация
|
|||
|
|
- [ ] Только обязательные поля
|
|||
|
|
- [ ] Без paths
|
|||
|
|
- [ ] Без components
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### Этап 3: Вспомогательные функции
|
|||
|
|
|
|||
|
|
#### 3.1. tests/helpers/setup.ts
|
|||
|
|
- [ ] `beforeEach` для инициализации
|
|||
|
|
- [ ] `afterEach` для очистки
|
|||
|
|
- [ ] Создание временных директорий
|
|||
|
|
- [ ] Очистка временных файлов
|
|||
|
|
|
|||
|
|
#### 3.2. tests/helpers/mock-server.ts
|
|||
|
|
- [ ] Настройка MSW
|
|||
|
|
- [ ] Mock handlers для разных endpoints
|
|||
|
|
- [ ] Симуляция различных HTTP статусов
|
|||
|
|
- [ ] Симуляция network errors
|
|||
|
|
- [ ] Симуляция timeouts
|
|||
|
|
|
|||
|
|
#### 3.3. tests/helpers/fixtures.ts
|
|||
|
|
- [ ] Загрузка фикстур
|
|||
|
|
- [ ] Валидация OpenAPI спецификаций
|
|||
|
|
- [ ] Создание тестовых конфигураций
|
|||
|
|
- [ ] Утилиты для сравнения сгенерированного кода
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### Этап 4: Юнит тесты CLI (15 кейсов)
|
|||
|
|
|
|||
|
|
#### 4.1. tests/unit/cli.test.ts - базовые сценарии
|
|||
|
|
- [ ] ✅ Запуск с корректными параметрами (локальный файл)
|
|||
|
|
- [ ] ✅ Запуск с URL в качестве input
|
|||
|
|
- [ ] ✅ Генерация с кастомным именем файла
|
|||
|
|
- [ ] ✅ Генерация с автоматическим именем (из OpenAPI title)
|
|||
|
|
- [ ] ✅ Отображение версии `--version`
|
|||
|
|
- [ ] ✅ Отображение help `--help`
|
|||
|
|
|
|||
|
|
#### 4.2. tests/unit/cli.test.ts - обработка ошибок
|
|||
|
|
- [ ] ❌ Отсутствие обязательного параметра `--input`
|
|||
|
|
- [ ] ❌ Отсутствие обязательного параметра `--output`
|
|||
|
|
- [ ] ❌ Несуществующий входной файл
|
|||
|
|
- [ ] ❌ Некорректный формат OpenAPI
|
|||
|
|
- [ ] ❌ Недоступный URL (404)
|
|||
|
|
- [ ] ❌ Недоступный URL (network error)
|
|||
|
|
- [ ] ❌ Невозможность записи в output директорию (permissions)
|
|||
|
|
- [ ] ❌ Невалидный JSON в input файле
|
|||
|
|
- [ ] ❌ YAML файл (должен работать или показать понятную ошибку)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### Этап 5: Юнит тесты генератора (20 кейсов)
|
|||
|
|
|
|||
|
|
#### 5.1. tests/unit/generator.test.ts - корректная генерация
|
|||
|
|
- [ ] ✅ Создание выходного файла
|
|||
|
|
- [ ] ✅ Корректная структура сгенерированного кода
|
|||
|
|
- [ ] ✅ Обработка GET запросов
|
|||
|
|
- [ ] ✅ Обработка POST запросов
|
|||
|
|
- [ ] ✅ Обработка PUT запросов
|
|||
|
|
- [ ] ✅ Обработка PATCH запросов
|
|||
|
|
- [ ] ✅ Обработка DELETE запросов
|
|||
|
|
- [ ] ✅ Генерация типов для request parameters
|
|||
|
|
- [ ] ✅ Генерация типов для response
|
|||
|
|
- [ ] ✅ Обработка path параметров
|
|||
|
|
- [ ] ✅ Обработка query параметров
|
|||
|
|
- [ ] ✅ Обработка request body
|
|||
|
|
- [ ] ✅ Генерация enum'ов
|
|||
|
|
- [ ] ✅ Обработка Bearer authentication
|
|||
|
|
- [ ] ✅ Применение хука `onFormatRouteName` (убирание "Controller")
|
|||
|
|
- [ ] ✅ Использование baseUrl из OpenAPI servers
|
|||
|
|
|
|||
|
|
#### 5.2. tests/unit/generator.test.ts - edge cases
|
|||
|
|
- [ ] ❌ Пустая OpenAPI спецификация
|
|||
|
|
- [ ] ❌ Минимальная спецификация (только paths)
|
|||
|
|
- [ ] ❌ Очень большая спецификация (100+ endpoints)
|
|||
|
|
- [ ] ❌ Unicode символы в именах методов/типов
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### Этап 6: Юнит тесты утилит (10 кейсов)
|
|||
|
|
|
|||
|
|
#### 6.1. tests/unit/utils/file.test.ts
|
|||
|
|
- [ ] ✅ `fileExists()` - существующий файл возвращает true
|
|||
|
|
- [ ] ✅ `fileExists()` - несуществующий файл возвращает false
|
|||
|
|
- [ ] ✅ `readJsonFile()` - чтение локального файла
|
|||
|
|
- [ ] ✅ `readJsonFile()` - чтение файла по URL
|
|||
|
|
- [ ] ❌ `readJsonFile()` - невалидный JSON выбрасывает ошибку
|
|||
|
|
- [ ] ❌ `readJsonFile()` - недоступный URL выбрасывает ошибку
|
|||
|
|
- [ ] ✅ `ensureDir()` - создание директории
|
|||
|
|
- [ ] ✅ `ensureDir()` - создание вложенных директорий
|
|||
|
|
- [ ] ✅ `writeFileWithDirs()` - запись файла с автосозданием директорий
|
|||
|
|
|
|||
|
|
#### 6.2. tests/unit/config.test.ts
|
|||
|
|
- [ ] ✅ Валидация корректной конфигурации успешна
|
|||
|
|
- [ ] ❌ Валидация без inputPath выбрасывает ошибку
|
|||
|
|
- [ ] ❌ Валидация без outputPath выбрасывает ошибку
|
|||
|
|
- [ ] ✅ Опциональное поле fileName работает
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### Этап 7: Тесты сгенерированного клиента (7 кейсов)
|
|||
|
|
|
|||
|
|
#### 7.1. tests/integration/generated-client.test.ts - компиляция
|
|||
|
|
- [ ] ✅ TypeScript компиляция без ошибок
|
|||
|
|
- [ ] ✅ Отсутствие type errors
|
|||
|
|
- [ ] ✅ Корректные импорты и экспорты
|
|||
|
|
|
|||
|
|
#### 7.2. tests/integration/generated-client.test.ts - корректность API
|
|||
|
|
- [ ] ✅ Все endpoints из спецификации присутствуют
|
|||
|
|
- [ ] ✅ Корректные имена методов (без "Controller" префиксов)
|
|||
|
|
- [ ] ✅ HttpClient правильно инициализируется
|
|||
|
|
- [ ] ✅ Метод `setSecurityData` работает
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### Этап 8: Интеграционные E2E тесты (15 кейсов)
|
|||
|
|
|
|||
|
|
#### 8.1. tests/integration/e2e-generation.test.ts - полный цикл
|
|||
|
|
- [ ] ✅ CLI генерация → создание файла → импорт → использование
|
|||
|
|
- [ ] ✅ Генерация из локального файла
|
|||
|
|
- [ ] ✅ Генерация из URL
|
|||
|
|
- [ ] ✅ Повторная генерация (перезапись файлов)
|
|||
|
|
|
|||
|
|
#### 8.2. tests/integration/e2e-generation.test.ts - HTTP запросы с mock
|
|||
|
|
- [ ] ✅ GET запрос без параметров
|
|||
|
|
- [ ] ✅ GET запрос с query параметрами
|
|||
|
|
- [ ] ✅ POST запрос с body
|
|||
|
|
- [ ] ✅ PUT запрос
|
|||
|
|
- [ ] ✅ PATCH запрос
|
|||
|
|
- [ ] ✅ DELETE запрос
|
|||
|
|
- [ ] ✅ Обработка 200 статуса
|
|||
|
|
- [ ] ✅ Обработка 201 статуса
|
|||
|
|
- [ ] ❌ Обработка 400 статуса (Bad Request)
|
|||
|
|
- [ ] ❌ Обработка 401 статуса (Unauthorized)
|
|||
|
|
- [ ] ❌ Обработка 404 статуса (Not Found)
|
|||
|
|
- [ ] ❌ Обработка 500 статуса (Server Error)
|
|||
|
|
- [ ] ❌ Обработка network errors
|
|||
|
|
- [ ] ✅ Bearer token authentication
|
|||
|
|
- [ ] ✅ Custom headers
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### Этап 9: Тесты производительности (5 кейсов)
|
|||
|
|
|
|||
|
|
#### 9.1. tests/integration/performance.test.ts
|
|||
|
|
- [ ] ✅ Генерация маленькой спецификации (< 1 секунды)
|
|||
|
|
- [ ] ✅ Генерация средней спецификации (< 3 секунд)
|
|||
|
|
- [ ] ✅ Генерация большой спецификации (< 10 секунд)
|
|||
|
|
- [ ] ✅ Параллельная генерация нескольких проектов
|
|||
|
|
- [ ] ✅ Повторная генерация не замедляется
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### Этап 10: Настройка CI (опционально)
|
|||
|
|
|
|||
|
|
#### 10.1. GitHub Actions
|
|||
|
|
- [ ] Создать `.github/workflows/test.yml`
|
|||
|
|
- [ ] Настроить запуск тестов на push
|
|||
|
|
- [ ] Настроить запуск тестов на PR
|
|||
|
|
- [ ] Добавить badge в README.md
|
|||
|
|
|
|||
|
|
#### 10.2. Pre-commit hooks
|
|||
|
|
- [ ] Установить husky
|
|||
|
|
- [ ] Добавить pre-commit хук для запуска тестов
|
|||
|
|
- [ ] Добавить lint-staged для проверки только измененных файлов
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### Этап 11: Документация
|
|||
|
|
|
|||
|
|
#### 11.1. Обновление README.md
|
|||
|
|
- [ ] Добавить секцию "Тестирование"
|
|||
|
|
- [ ] Описать команды запуска тестов
|
|||
|
|
- [ ] Добавить информацию о coverage
|
|||
|
|
- [ ] Добавить примеры запуска конкретных тестов
|
|||
|
|
|
|||
|
|
#### 11.2. Создание CONTRIBUTING.md
|
|||
|
|
- [ ] Правила написания тестов
|
|||
|
|
- [ ] Структура тестов
|
|||
|
|
- [ ] Как добавить новый тест
|
|||
|
|
- [ ] Требования к coverage
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Команды для разработки
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# Установка зависимостей
|
|||
|
|
bun install
|
|||
|
|
|
|||
|
|
# Запуск всех тестов
|
|||
|
|
bun test
|
|||
|
|
|
|||
|
|
# Запуск только юнит тестов
|
|||
|
|
bun test:unit
|
|||
|
|
|
|||
|
|
# Запуск только интеграционных тестов
|
|||
|
|
bun test:integration
|
|||
|
|
|
|||
|
|
# Запуск в watch режиме
|
|||
|
|
bun test:watch
|
|||
|
|
|
|||
|
|
# Запуск с coverage
|
|||
|
|
bun test:coverage
|
|||
|
|
|
|||
|
|
# Запуск конкретного файла
|
|||
|
|
bun test tests/unit/cli.test.ts
|
|||
|
|
|
|||
|
|
# Запуск конкретного теста
|
|||
|
|
bun test -t "should generate client with custom name"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Метрики успеха
|
|||
|
|
|
|||
|
|
### Критерии завершения
|
|||
|
|
- ✅ Все 72 тестовых кейса реализованы
|
|||
|
|
- ✅ Coverage > 80% (желательно > 90%)
|
|||
|
|
- ✅ Все тесты проходят успешно
|
|||
|
|
- ✅ Время выполнения всех тестов < 30 секунд
|
|||
|
|
- ✅ CI настроен и работает
|
|||
|
|
- ✅ Документация обновлена
|
|||
|
|
|
|||
|
|
### Показатели качества
|
|||
|
|
- 🎯 **Coverage:** > 90%
|
|||
|
|
- 🎯 **Скорость:** < 30 сек для всех тестов
|
|||
|
|
- 🎯 **Стабильность:** 0 flaky тестов
|
|||
|
|
- 🎯 **Читаемость:** Понятные названия и описания
|
|||
|
|
- 🎯 **Поддерживаемость:** Минимум дублирования кода
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Следующие шаги
|
|||
|
|
|
|||
|
|
После завершения всех этапов:
|
|||
|
|
|
|||
|
|
1. **Переключение в режим Code** для реализации
|
|||
|
|
2. **Пошаговая реализация** согласно чек-листам
|
|||
|
|
3. **Проверка coverage** после каждого этапа
|
|||
|
|
4. **Рефакторинг** при необходимости
|
|||
|
|
5. **Финальная проверка** всех тестов
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Примечания
|
|||
|
|
|
|||
|
|
- Все тесты должны быть изолированными и не зависеть друг от друга
|
|||
|
|
- Использовать temporary directories для всех файловых операций
|
|||
|
|
- Очищать ресурсы после каждого теста (cleanup)
|
|||
|
|
- Следовать принципу AAA (Arrange, Act, Assert)
|
|||
|
|
- Использовать описательные имена тестов
|
|||
|
|
- Группировать связанные тесты с помощью `describe`
|