Logo Light
Published on

Fitnotes (5. díl) - Testy filtrování, řazení a agregací v Prisma modelu

Testy filtrování, řazení a agregací v Prisma modelu

V předchozím dílu jsem implementoval CRUD testy. V tomto článku se zaměřím na složitější operace nad databází: filtrování podle různých podmínek, řazení výsledků a agregační dotazy.


1. Příprava dat pro testy

Před každým testem vymažemedatabázi a připravíme si několik vzorových záznamů, aby testy běžely nad smysluplnými daty.

Například:

  • Workout 1: 2024-10-11, Bench Press, Chest, 100 kg
  • Workout 2: 2024-10-12, Bench Press, Chest, 110 kg
  • Workout 3: 2024-11-01, Squat, Legs, 150 kg
  • Workout 4: 2024-12-01, Deadlift, Back, 200 kg
beforeEach(async () => {
  await prisma.workout.deleteMany() // vyčistit tabulku před každým testem

  await prisma.workout.createMany({
    data: [
      {
        date: new Date('2024-10-11'),
        exercise: 'Bench Press',
        category: 'Chest',
        weight: 100,
        weightUnit: 'kgs',
        reps: 8,
      },
      {
        date: new Date('2024-10-12'),
        exercise: 'Bench Press',
        category: 'Chest',
        weight: 110,
        weightUnit: 'kgs',
        reps: 6,
      },
      {
        date: new Date('2024-11-01'),
        exercise: 'Squat',
        category: 'Legs',
        weight: 150,
        weightUnit: 'kgs',
        reps: 5,
      },
      {
        date: new Date('2024-12-01'),
        exercise: 'Deadlift',
        category: 'Back',
        weight: 200,
        weightUnit: 'kgs',
        reps: 3,
      },
    ],
  })
})

2. Testy filtrování

Filtrování bude v aplikaci častá operace, proto je vhodné pokrýt všechny klíčové scenáře včetně hraničních hodnot (Boundary Value Analysis) a tříd ekvivalence (Equivalence Partitioning). Příklady kódu mají jen ukázat, jak testy rámcově vypadají.

2.1 Filtrování podle data

Scenáře:

  • získat všechny tréninky pro konkrétní den
  • otestovat hraniční hodnoty:
    • dnešní datum (mělo by vrátit prázdný výsledek)
    • 1.1.1970 (pravděpodobně prázdný výsledek)
    • datum před 1.1.1970
    • datum v budoucnosti
it('should return only workouts for a specific date', async () => {
  const result = await prisma.workout.findMany({
    where: { date: new Date('2024-10-11') },
  })

  expect(result).toHaveLength(1)
  expect(result[0].exercise).toBe('Bench Press')
  expect(result[0].weight).toBe(100)
})

2.2 Filtrování podle cviku

Scenáře:

  • vyhledávání podle jmena cviku (case-insensitive)
  • ošetření mezer a diakritiky (pokud bude v budoucnu potřeba)
  • vyhledání neexistujícího cviku
it('should return all workouts for Bench Press (case-insensitive)', async () => {
  const result = await prisma.workout.findMany({
    where: {
      exercise: {
        equals: 'bench press',
        mode: 'insensitive',
      },
    },
  })

  expect(result).toHaveLength(2)
})

3. Testy řazení

Scenáře:

  • seřadit tréninky podle data vzestupně
  • seřadit tréninky podle data sestupně
it('should sort workouts by date ascending', async () => {
  const result = await prisma.workout.findMany({
    orderBy: { date: 'asc' },
  })

  const dates = result.map((r) => r.date.getTime())
  const sorted = [...dates].sort((a, b) => a - b)
  expect(dates).toEqual(sorted)
})

Pro sestupné řazení bychom změnili orderBy: { date: 'desc' } a otestovali obdobně.


4. Agregační testy

Například nejvyšší zvednutá váha pro daný cvik:

it('should find the max weight for Bench Press', async () => {
  const maxWeight = await prisma.workout.aggregate({
    _max: { weight: true },
    where: { exercise: { equals: 'Bench Press' } },
  })

  expect(maxWeight._max.weight).toBe(110) // v testu bude vhodné mít tuto hodnotu v proměnné
})

Další možnosti agregací:

  • průměrná váha pro cvik (_avg)
  • počet tréninků v určitém období (_count)

5. Kombinace filtrování a řazení

Můžeme testovat například, že při filtrování podle kategorie Chest dostaneme tréninky jen z této kategorie a zároveň budou seřazené podle váhy sestupně.

it('should filter by category Chest and sort by weight desc', async () => {
  const result = await prisma.workout.findMany({
    where: { category: 'Chest' },
    orderBy: { weight: 'desc' },
  })

  expect(result).toHaveLength(2)
  expect(result[0].weight).toBeGreaterThanOrEqual(result[1].weight)
})

Co bude dál?

V dalším dílu se zaměříme na hromadné operace (import CSV) a testování částečně chybných vstupů.