Ana içeriğe atla

Mala Anlatır Gibi React — 11: Test Kütüphanesi / Vitest

Mala Anlatır Gibi React — 11: Test Kütüphanesi / Vitest

Bir program yazmak kadar, onun testini yazmakta önemlidir. Hele ki büyük projelerde kontrol etmenin zorlaşmasıyla beraber test kütüphanesi size yardımcı olacaktır.

Kütüphaneyi, şöyle hemen kurabilir ve kullanabilirsiniz:

npm install -D vitest

İlk olarak, package.json’a script eklememiz gerek:

"scripts": {
"test": "vitest",
}

Dosyaların adlarını şöyle yapmanız gerekiyor:

.test.

example.test.js

example.test.jsx

Vitest (Görsel, I.)

Hadi gelelim içeriğine:

Bir tane toplama işlemi oluşturalım:

import { expect } from 'vitest'

test('toplama işlemi doğru', () => {
expect(1 + 1).toBe(2)
})

it() ve test(): Bir test etme bloğu oluştururuz. it ve test fonksiyonları aynıdır.

describe(): Testleri gruplandırmak için kullanılır.

expect(): Sonucu yakalar.

Değer kontrol fonksiyonları:

.toBe(değer): Değerin aynı olup olmadığını kontrol eder.

.toContain(değer): Yazının içinde yazılan değerin varlığını kontrol eder.

.toEqual(obj, arr): Dizi ve nesnelerde kullanılır.

.toThrow(func): Fonksiyonun hata fırlatıp fırlatmadığını kontrol eder.

.toHaveProperty(değer): Bir nesne içerisinde belirli bir özelliğin var olup olmadığını kontrol eder.

.toBeNull(): Değerin Null olup olmadığını kontrol eder.

.toBeUndefined(): Değerin undefined olup olmadığını kontrol eder.

.toBeDefined(): Değerin tanımlı olup olmadığını kontrol eder.

.toBeTruthy(): Değer true dönüp dönmediğini kontrol eder.

.toBeFalsy(): Değer false dönüp dönmediğini kontrol eder.

.toBeGreaterThan(değer): Değer gelen değerden büyük mü kontrol eder.

.toBeLessThan(değer): Değer gelen değerden küçük mü kontrol eder.

.toBeGreaterThanOrEqual(değer).toBeLessThanOrEqual(değer): Sayısal büyüklük veya küçüklük karşılaştırmalarında eşitlik durumunu da kontrol eder.

.toMatch(): RegEx girmenizi sağlar.

.toStrictEqual(değer): Nesne içerisindeki tüm değerleri kontrol eder.

Test hayat döngüsü:

.beforeEach(func): Her testten önce çalışır.

.afterEach(func): Her testten sonra çalışır.

.beforeAll(func): Tüm testlerden önce çalışır.

.afterAll(func): Tüm testlerden önce çalışır.

React fonksiyonları:

Bu durumda ise devreye @testing-library/react kütüphanesi giriyor. npm i -D ile yine paketi kurabilirsiniz.

render() fonksiyonu kullanımı:

import { render } from '@testing-library/react'
test('App bileşeni doğru render ediliyor', () => {
const { getByText } = render(<App />)
expect(getByText('Merhaba Dünya!')).toBeInTheDocument()
})

.getByRole() ile screen() fonksiyonu kullanımı:

import App from './App'

test('Butonun metni doğru mu?', () => {
render(<App />)
const button = screen.getByRole('button', { name: 'Gönder' })
expect(button).toBeInTheDocument()
})

fireEvent(): DOM üzerinde olay (event) tetikler, örneğin bir butona tıklama veya bir input’a yazı yazma:

import { render, screen, fireEvent } from '@testing-library/react'
import Counter from './Counter';

test('Butona tıklayınca sayaç artıyor', () => {
render(<Counter />)
const button = screen.getByText('Artır')
fireEvent.click(button)
expect(screen.getByText('Sayaç: 1')).toBeInTheDocument()
})

userEvent(): Kullanıcı etkileşimlerini (daha gerçekçi şekilde) simüle eder. fireEvent'in daha gelişmiş bir alternatifi gibi düşünebilirsin.

import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import LoginPage from './LoginPage';

test('Kullanıcı giriş yapabiliyor', async () => {
render(<LoginPage />)
const usernameInput = screen.getByLabelText('Kullanıcı Adı')
const passwordInput = screen.getByLabelText('Şifre')
const loginButton = screen.getByRole('button', { name: 'Giriş Yap' })

await userEvent.type(usernameInput, 'burakbehlul')
await userEvent.type(passwordInput, 'burak123')
await userEvent.click(loginButton)

expect(screen.getByText('Hoş geldiniz, burakbehlul!')).toBeInTheDocument()
})

waitFor(): Bir async işlemin tamamlanmasını bekler. Örneğin, bir API çağrısı sonrası DOM’da değişiklik olmasını test etmek için kullanılır:

import { render, screen, waitFor } from '@testing-library/react'
import FetchComponent from './FetchComponent'

test('API çağrısı sonrası veri doğru görünüyor', async () => {
render(<FetchComponent />)
await waitFor(() => expect(screen.getByText('Veri yüklendi')).toBeInTheDocument())
})

toBeInTheDocument(): Elemanın DOM’da bulunup bulunmadığını kontrol eder:

expect(screen.getByText('Merhaba Dünya!')).toBeInTheDocument()

toHaveClass(): Bir elemanın belirli bir CSS sınıfını taşıyıp taşımadığını kontrol eder:

const button = screen.getByRole('button')
expect(button).toHaveClass('primary-button')

toHaveAttribute(): Bir elemanın belirli bir HTML attribute’a sahip olup olmadığını kontrol eder:

const input = screen.getByLabelText('Email')
expect(input).toHaveAttribute('type', 'email')

findBy ve queryBy:

  • findBy: Bir async element aramak için kullanılır.
  • queryBy: Bir elementin DOM'da olmadığını test etmek için kullanılır.
const element = await screen.findByText('Yükleniyor...')
expect(screen.queryByText('Hata')).not.toBeInTheDocument()

Yapılandırma

vite.config.js’e gelin ve dosyaya şunu yazın:

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react'

export default defineConfig({
plugins: [react()],
test: {
environment: 'jsdom',
globals: true,
setupFiles: './vitest.setup.ts'
}
})

vitest.setup.js:

import '@testing-library/jest-dom'

Örnekler:

State Kontrolü: Bir butona tıklayınca state değişimini kontrol edebilirsin:

test('Butona tıklayınca state değişiyor', () => {
render(<Counter />)
const button = screen.getByRole('button', { name: 'Artır' })
fireEvent.click(button)
expect(screen.getByText('Sayaç: 1')).toBeInTheDocument()
})

Props Kontrolü: Bir bileşene gönderilen props’ların doğru çalışıp çalışmadığını kontrol edebilirsin:

test('Bileşen doğru props ile render ediliyor', () => {
render(<Greeting name="Ümit" />)
expect(screen.getByText('Merhaba, Ümit!')).toBeInTheDocument()
})

API Çağrısı ve Loader: Bir API çağrısı sırasında loader’ın görünmesini test edebilirsin:

test('Loader doğru çalışıyor', async () => {
render(<FetchComponent />)
expect(screen.getByText('Yükleniyor...')).toBeInTheDocument()
await waitFor(() => expect(screen.getByText('Veri yüklendi')).toBeInTheDocument())
})

Gerekli olacak tüm kullanımları size sundum. Olası kod yazımları da sundum.

Vitest kütüphanesi böyleydi. Diğer iki kütüphane: Jest ve Cypress ile ilgili de yazılar gelebilir. Genelde jest çok kullanılan bir kütüphane fakat Vitest onun yerini alacak gibi.

Herkese iyi kodlamalar!

Yorumlar