tests.md 14 KB

Тестовое покрытие проекта Stroyprofit CRM

Текущее состояние

Инфраструктура тестирования

  • Фреймворк: PHPUnit 11
  • Доп. зависимости: Mockery (подключён, но не используется), Faker (используется в фабриках)
  • БД в тестах: реальная MySQL (SQLite закомментирован в phpunit.xml)
  • Сброс БД: RefreshDatabase + $seed = true в каждом тест-классе
  • Моки: не применяются — все зависимости реальные (интеграционный стиль)

Статистика

Категория Всего файлов Покрыто Покрытие
Тест-файлов 29
Тест-методов ~302
Модели 34 5 ~15%
Сервисы 28 13 ~46%
Jobs 21 0 0%
Контроллеры 30 4 ~13%
Form Requests 22 0 0%
Helpers 5 3 60%
Observers 1 1 100%

Что покрыто тестами

Unit — Helpers

  • CountHelper — числительные (единицы/2-4/5+)
  • DateHelper — конвертация дат (Excel, ISO, человеческий формат)
  • Price — форматирование цен с символом ₽

Unit — Models

  • Order — константы статусов, атрибуты, связи, soft delete
  • Reclamation — константы статусов, связи, activeReservations, openShortages
  • InventoryMovement — константы типов, акцессоры, связи, скоупы, касты
  • Shortage — статусы, акцессоры, связи, скоупы, методы addReserved/recalculate
  • SparePartOrder — статусы, reserved_qty, free_qty, canReserve, скоупы
  • SparePart — цены в копейках, складские остатки, резервы, minimum stock

Unit — Services

  • FileService — сохранение файлов (Unicode, спецсимволы, дубликаты)
  • GenerateDocumentsService — генерация ZIP-архивов, монтаж/сдача/рекламация (частично через markTestSkipped)
  • ImportOrdersService — импорт заказов из Excel
  • ShortageService — FIFO, processPartOrderReceipt, calculateOrderQuantity, getCriticalShortages
  • SparePartInventoryService — getStockInfo, getInventorySummary, getBelowMinStock
  • SparePartIssueService — issueReservation, issueForReclamation, directIssue, correctInventory
  • SparePartReservationService — reserve, cancelForReclamation, adjustReservation
  • Export/ExportAreasService — экспорт районов в XLSX
  • Export/ExportDistrictsService — экспорт округов в XLSX
  • Import/ImportAreasService — импорт районов (создание, обновление, восстановление)
  • Import/ImportDistrictsService — импорт округов
  • Import/ImportMafOrdersService — импорт MAF-заказов
  • Import/ImportSparePartOrdersService — импорт заказов запчастей

Unit — Observers

  • SparePartOrderObserver — автопокрытие shortages при создании/обновлении заказа

Feature

  • AdminAreaController — CRUD + import/export (16 тестов)
  • AdminDistrictController — CRUD + import/export (15 тестов)
  • OrderController — CRUD, MAF-операции, фото, документы, генерация, экспорт (22 теста)
  • ReclamationController — CRUD, файлы, запчасти, детали, генерация (22 теста)

Доработки

Приоритет 1 — Критически важно

1.1 Перевести БД на SQLite in-memory для тестов

Файл: phpunit.xml

Раскомментировать строки:

<env name="DB_CONNECTION" value="sqlite"/>
<env name="DB_DATABASE" value=":memory:"/>

Текущая конфигурация требует запущенную MySQL, что делает запуск тестов в CI и на чистой машине невозможным без дополнительной настройки. Нужно убедиться, что все миграции совместимы с SQLite (убрать специфичные для MySQL типы: jsontext, enumstring, fulltext-индексы).

1.2 Покрыть Jobs тестами (0% покрытие)

Все 21 джоб не имеют тестов. Минимально необходимо покрыть:

Job Что тестировать
ExportOrdersJob диспетчеризация, создание файла, статус Import
ExportMafJob аналогично
ExportReclamationsJob аналогично
ExportScheduleJob аналогично
GenerateFilesPack создание ZIP, корректность содержимого
GenerateInstallationPack аналогично
GenerateHandoverPack аналогично
ImportJob обработка файла, ошибки валидации
NotifyManagerNewOrderJob отправка уведомления (мок FCM)
NotifyManagerChangeStatusJob аналогично

Рекомендация: использовать Queue::fake() + Bus::fake() для проверки диспетчеризации без реального выполнения.

1.3 Подключить Mockery и использовать моки

Сейчас все тесты сервисов — интеграционные (реальная БД). Это медленно и хрупко. Нужно добавить unit-тесты с моками для изоляции зависимостей:

// Пример: мокировать репозиторий в SparePartReservationService
$sparePart = Mockery::mock(SparePart::class);
$sparePart->shouldReceive('lockForUpdate')->andReturnSelf();

Приоритет 2 — Важно

2.1 Покрыть контроллеры Feature-тестами

Не покрытые контроллеры с высоким бизнес-приоритетом:

Контроллер Что тестировать
MafOrderController CRUD, статусы, документы
SparePartController CRUD, цены, остатки
SparePartOrderController создание, статусы, отгрузки
SparePartReservationController резервирование, отмена
SparePartInventoryController инвентаризация
ContractController CRUD, загрузка файлов
ScheduleController создание расписания из заказа/рекламации
ImportController загрузка файла, диспетчеризация джоба
ReportController генерация отчётов, фильтрация
ProductController / ProductSKUController CRUD каталога
UserController создание, редактирование пользователей

Минимальный набор тестов для каждого контроллера:

  • Неаутентифицированный запрос → редирект на логин
  • Успешный запрос → корректный ответ (200/redirect)
  • Невалидные данные → 422 / ошибки валидации
  • Авторизация (роли) — если применима

2.2 Покрыть Form Requests тестами

22 Request-класса не имеют изолированных тестов. Добавить тесты валидации:

// tests/Unit/Requests/StoreOrderRequestTest.php
public function test_required_fields(): void
{
    $request = new StoreOrderRequest();
    $validator = Validator::make([], $request->rules());
    $this->assertTrue($validator->fails());
    $this->assertArrayHasKey('client_name', $validator->errors()->toArray());
}

Приоритетные Request-классы:

  • Order/StoreOrderRequest — основная форма заказа
  • StoreMafOrderRequest — форма MAF
  • StoreReclamationRequest / StoreReclamationDetailsRequest
  • StoreSparePartOrderRequest / ShipSparePartOrderRequest
  • StoreContractRequest

2.3 Покрыть непокрытые сервисы

Сервис Что тестировать
ExportOrdersService формирование XLSX, корректность данных
ExportMafService аналогично
ExportReclamationsService аналогично
ExportScheduleService аналогично
ExportSparePartsService аналогично
ImportReclamationsService импорт, маппинг, ошибки
ImportMafsService аналогично
ImportCatalogService создание/обновление товаров
Import/ImportSparePartsService аналогично
Import/ImportYearDataService аналогично
PdfConverterClient HTTP-запрос к PDF-сервису (мок HTTP-клиента)
Export/ExportYearDataService аналогично

Приоритет 3 — Желательно

3.1 Покрыть непокрытые модели

Модели без тестов (нет отдельных тест-файлов):

  • MafOrder — статусы, связи, атрибуты
  • Product / ProductSKU — связи, SKU-логика
  • Contract — связи, загрузка файлов
  • Schedule — связи с Order/Reclamation, статусы
  • Reservation — связи, статусы, количество
  • SparePartOrderShipment — списание резервов
  • Dictionary/Area / Dictionary/District — soft delete, связи
  • Database Views (OrderView, MafOrdersView и т.д.) — корректность агрегации

3.2 Покрыть непокрытые Helpers

  • ExcelHelper — форматирование ячеек, типы данных
  • roles.php — проверка наличия/наименования ролей

3.3 Добавить тесты для Auth-контроллеров

Покрыть базовые сценарии аутентификации:

  • Успешный логин
  • Логин с неверным паролем
  • Выход из системы
  • Сброс пароля (если используется)

3.4 Добавить тесты политик авторизации (Policies/Gates)

Если в проекте есть ролевая модель (файл roles.php, Role модель) — добавить тесты:

  • Доступ к admin-контроллерам только для admin-роли
  • Запрет доступа для пользователей без нужной роли

3.5 Настроить покрытие кода (Coverage)

Добавить генерацию HTML-отчёта покрытия:

<!-- phpunit.xml -->
<coverage>
    <report>
        <html outputDirectory="coverage"/>
        <clover outputFile="coverage.xml"/>
    </report>
</coverage>

Требуется Xdebug или PCOV. Добавить в Makefile:

make test-coverage   # php artisan test --coverage

Технические проблемы

Тесты зависят от наличия Excel-шаблонов

GenerateDocumentsServiceTest использует markTestSkipped() если шаблоны отсутствуют в /templates/. Нужно:

  • Добавить тестовые шаблоны в tests/fixtures/templates/
  • Или сделать шаблоны доступными в CI через переменную окружения

Фикстура tests/fixtures/test_orders_import.xlsx

ImportOrdersServiceTest требует реальный xlsx-файл. Убедиться что файл находится в git и содержит актуальные данные.

Нет изоляции тестов сервисов

Все Unit-тесты сервисов реально обращаются к БД — это интеграционные тесты. Нужно:

  • Переименовать директорию tests/Unit/Services/tests/Integration/Services/
  • Или создать настоящие Unit-тесты с моками зависимостей

Рекомендуемый порядок выполнения доработок

  1. Настроить SQLite in-memory в phpunit.xml (быстрый прогресс без кода)
  2. Покрыть MafOrderController Feature-тестами (высокий бизнес-приоритет)
  3. Покрыть SparePartController + SparePartOrderController Feature-тестами
  4. Добавить тесты для ExportOrdersService и других экспорт-сервисов
  5. Покрыть Form Requests тестами (быстро, высокая ценность)
  6. Добавить тесты для Jobs с Queue::fake()
  7. Настроить Coverage-отчёт
  8. Добавить тесты Auth-контроллеров
  9. Покрыть оставшиеся модели и контроллеры