🧪 Контроль качества

Методология тестирования

137 сквозных тестов проверяют, что каждый SQL-запрос точно совпадает с выводом Prisma

137
E2E-тестов
Каждый запрос проверен
100%
Полное соответствие
Побайтовое совпадение
2
Движка БД
PostgreSQL и SQLite
3
Бенчмарки ORM
Prisma v6/v7, Drizzle

Как мы проверяем корректность

Каждый тест проходит строгий 5-этапный процесс валидации, чтобы убедиться, что сгенерированный SQL даёт идентичные результаты Prisma

1

Генерация SQL из запроса Prisma

Парсинг аргументов Prisma и генерация эквивалентного SQL на основе тех же моделей и схемы. Сгенерированный SQL использует параметризованные запросы для безопасности и производительности.

2

Параллельное выполнение обоих запросов

Выполнение сгенерированного SQL напрямую через postgres.js или better-sqlite3 и выполнение того же запроса через Prisma. Оба запроса работают с одним состоянием базы.

3

Нормализация результатов

Обработка различий типов (BigInt vs Number, точность Decimal, сериализация Date) и нормализация порядка ключей объектов для честного сравнения.

4

Глубокая проверка равенства

Проверка точного совпадения: одинаковое количество строк, те же значения полей, те же вложенные связи, тот же порядок. Любое несовпадение приводит к провалу теста.

5

Бенчмарк производительности

Измерение времени выполнения с 5 разогревочными запусками, затем усреднение 10-50 итераций на тест. Сравнение с Prisma v6, Prisma v7 и Drizzle ORM.

Продвинутые техники валидации

Нормализация типов данных

  • Конвертация BigInt: JavaScript BigInt → Number для сравнения
  • Обработка Decimal: Prisma Decimal → Float с точностью 10 знаков
  • Нормализация дат: Все DateTime значения → null (фокус на данных, не на временных метках)
  • Парсинг JSON: Автоматическое определение и парсинг JSON строк
  • Сортировка ключей объектов: Алфавитный порядок для консистентного сравнения

Бенчмаркинг производительности

  • Фаза разогрева: 5 итераций для прогрева кэшей и JIT
  • Адаптивные итерации: 5-50 запусков в зависимости от сложности запроса
  • Изолированное измерение: Каждый тип запроса измеряется независимо
  • Сравнение нескольких ORM: Prisma v6, v7, Drizzle, Generated SQL
  • Время генерации SQL: Отдельный замер накладных расходов генерации запросов

Полное покрытие тестами

Тесты покрывают все операции чтения Prisma на разных уровнях сложности

Операции запросов

  • findMany со сложными фильтрами
  • findFirst с skip и пагинацией
  • findUnique по ID и уникальным полям
  • count с условиями WHERE
  • aggregate (sum, avg, min, max)
  • groupBy с условиями HAVING

Сложные сценарии

  • Вложенные include (4 уровня)
  • Фильтры связей (some/every/none)
  • Distinct с оконными функциями
  • Курсорная пагинация
  • Select + include вместе
  • Подсчёт связей (_count)

Типы фильтров

  • Сравнения (lt/lte/gt/gte)
  • Логические (AND/OR/NOT)
  • Строковые операции (contains/startsWith)
  • Проверка NULL (is/isNot)
  • IN/NOT IN массивы
  • Режимы регистра

Тестирование PostgreSQL

  • ✓ ILIKE регистронезависимый поиск
  • ✓ Операции с JSON/JSONB
  • ✓ Обработка массивов
  • ✓ Поддержка составных типов
  • ✓ Валидация оконных функций
  • ✓ Тестирование изоляции транзакций

Тестирование SQLite

  • ✓ LIKE сопоставление паттернов
  • ✓ Валидация расширения JSON1
  • ✓ Эмуляция оконных функций
  • ✓ Оптимизация DISTINCT
  • ✓ Корреляция подзапросов
  • ✓ Обработка текстовой аффинности

Пример тестового случая

Как мы проверяем сложный вложенный запрос с фильтрами связей

tests/e2e/postgres.test.ts
it('nested relation filter', () =>
  runParityTest(
    db,
    benchmarkResults,
    'findMany nested relation',
    'Organization',
    {
      method: 'findMany',
      where: {
        projects: {
          some: {
            tasks: { some: { status: 'DONE' } }
          }
        }
      }
    },
    () => db.prisma.organization.findMany({
      where: {
        projects: {
          some: {
            tasks: { some: { status: 'DONE' } }
          }
        }
      },
      orderBy: { id: 'asc' }
    }),
  )
)

// runParityTest внутри:
// 1. Вызывает generateSQL() с аргументами
// 2. Выполняет сгенерированный SQL напрямую
// 3. Выполняет запрос Prisma
// 4. Нормализует оба результата
// 5. Глубокая проверка равенства - падает при любом различии
// 6. Бенчмарк времени выполнения

Что происходит при выполнении теста

1. Генерация запроса (микросекунды)

Функция generateSQL() парсит аргументы Prisma и создаёт параметризованный SQL. Этот шаг измеряется отдельно для оценки накладных расходов генерации.

2. Параллельное выполнение (миллисекунды)

Оба запроса обращаются к одному состоянию БД одновременно через Promise.all(), обеспечивая честное сравнение и идентичные условия данных.

3. Глубокая нормализация

Результаты проходят рекурсивную нормализацию: BigInt→Number, Decimal→Float(10), Date→null, парсинг JSON, сортировка ключей. Это гарантирует побайтовую точность сравнения.

4. Строгое равенство

Сравнение через JSON stringify с нулевой толерантностью. Любое несовпадение в количестве строк, значениях полей, вложенных объектах или порядке приводит к провалу теста с детальным выводом различий.

5. Измерение производительности

После валидации 5-50 итераций измеряют среднее время выполнения. Результаты включают: Prisma v6, Prisma v7, Drizzle ORM, Generated SQL и накладные расходы генерации SQL.

Мультиверсионная валидация

Каждый тест запускается как с Prisma v6, так и с v7 для гарантии совместимости между версиями:

Prisma v6 (6.16.3)

  • • Прямое использование PrismaClient
  • • Устаревшая архитектура движка
  • • Базовые метрики производительности

Prisma v7 (7.2.0)

  • • Архитектура на основе адаптеров
  • • @prisma/adapter-pg и adapter-better-sqlite3
  • • Новые оптимизации движка

Автоматические отчёты бенчмарков

Все результаты бенчмарков автоматически генерируются и сохраняются в JSON файлы для полной прозрачности:

benchmark-results/v6-postgres-latest.json
benchmark-results/v7-postgres-latest.json
benchmark-results/v6-sqlite-latest.json
benchmark-results/v7-sqlite-latest.json

Каждый файл содержит: название теста, время выполнения Prisma, время генерации SQL, время Drizzle, коэффициенты ускорения и ISO временную метку.

Изучите полный набор тестов

Все 137 тестов с открытым исходным кодом. Просмотрите тестовый код, бенчмарки и логику валидации.