Temel React. JS Test Yazma Eğitimi

React, günümüzde en popüler ve yaygın olarak kullanılan JavaScript kütüphanelerinden biridir.  Bu yazımda, React uygulamalarını test etmek için kullanılan en yaygın araçlardan biri olan React Testing Library (RTL) ve Jest‘i kullanarak react’e nasıl test yazılır adım adım göstereceğim.

React’e üç temel test türü bulunmaktadır;

  1. Birim (Unit ) Testleri: Tek bir fonksiyonu veya componenti test etmek için kullanılır.
  2. Entegrasyon (Integration) Testleri: Birden fazla componentin bir arada çalışmasını test etmek için kullanılır.
  3. Uçtan Uca (E2E) Testleri: Uygulamanın tamamını test etmek için kullanılır.

Kurulum:

Terminal kullanarak Jest ve React Testing Library kurulumu için aşağıdaki komutları çalıştırın:

Jest’in Kurulumu:

npm install --save-dev jest

React Testing Library’nin Kurulumu:

npm install --save-dev @testing-library/react

Jest kurulduktan sonra React projesinde test dosyları oluşturabiliriz. Jest, proje dizinindeki .test.js veya .spec.js ile biten dosyaları otomatik olarak tanır. Test dosyaları *.test.js veya *.spec.js uzantısına sahip olmalıdır.

Jest ve RTL’de kullanılan bazı temel değişkenler ve işlevleri şunlardır;

Jest

  1. describe: Testleri gruplamak için kullanılır.
  2. it veya test: Test işlemi tanımlamak için kullanılır.
  3. expect: Doğrulama yapmak için kullanılır. Bir değeri, beklenen sonuç ile karşılaştırır.
  4. beforeEach: Her test çalışmadan önce belirtilen işlevi çalıştırır.
  5. afterEach: Her test çalıştıktan sonra belirtilen işlevi çalıştırır.
  6. beforeAll: Tüm testler başlamadan önce bir kere çalıştırılacak işlevi tanımlar.
  7. afterAll: Tüm testler tamamlandıktan sonra bir kere çalıştırılacak işlevi tanımlar.

React Testing Library (RTL):

  1. render: Bileşeni sanal bir DOM’a render etmek için kullanılır.
  2. screen: Bileşen üzerinde işlem yapmak için kullanılır.
  3. getBy: Bir elementi etiket adına göre seçmek için kullanılır.
  4. queryBy: Bir elementi etiket adına göre sorgulamak için kullanılır. Bulunamazsa null döner.
  5. findBy: Asenkron bir şekilde bir elementi etiket adına göre bulmak için kullanılır. Promise döner.
  6. waitFor: Belirli bir durumun gerçekleşmesini beklemek için kullanılır.
  7. fireEvent: Belirli bir olayı tetiklemek için kullanılır.
  8. within: Bir bileşenin belirli bir kısmında arama yapmak için kullanılır.
  9. debug: Bileşeni veya DOM’u görüntülemek için kullanılır.

Uygulama

Şimdi, bir örnek uygulama geliştirerelim.

Örnek uygulamada, ürünün görselini, ismini, fiyatını ve sayısını gösteren bir ürün kartı componenti geliştirip ardından testlerini yazmaya başlayacağız.

1. Test grubunu oluşturuyoruz.

describe("ProductCard Component Testi", () => {});

2. Ürün kartı başarılı şekilde render edildiğinin ve ürün bilgilerinin doğrulunu kontrol etmek için ilk testimizi yazıyoruz.

it("Ürün kartı başarılı şekilde render edilmelidir", () => {
  // ProductCard bileşenini render ediyoruz.
  render(<ProductCard />);

  // Ürün bilgisi doğru mu?
  expect(screen.getByText("iPhone 15 Pro")).toBeInTheDocument(); // Ürün adı doğru bir şekilde "iPhone 15 Pro" olarak gösteriliyor mu?
  expect(screen.getByText("100")).toBeInTheDocument(); // Fiyat doğru bir şekilde 100 olarak gösteriliyor mu?

  // Ürün resmi doğru mu?
  const productImage = screen.getByAltText("iPhone 15 Pro"); 
  expect(productImage).toBeInTheDocument(); 
  expect(productImage.src).toBe(
    "https://onursahin.net/wp-content/uploads/2022/03/images.png"
  );
});

3. Add Cart butonuna tıklanıldığında count sayısı artıyor mu?

it("Add Cart butonuna tıklandığında ürün sayısının artması gerekmektedir", () => {
  render(<ProductCard />);
  fireEvent.click(screen.getByText("Add Cart")); // "Add Cart" butonuna tıklıyoruz.
  expect(screen.getByText("Count: 1")).toBeInTheDocument(); // Sepetteki ürün sayısı 1 olmalıdır.
});

4. Remove Cart” butonuna tıklanınca ürün sayısı sıfırlanıyor mu?

it("Remove Cart butonuna tıklandığında ürünün sepetten kaldırılması gerekmektedir", () => {
  render(<ProductCard />);
  fireEvent.click(screen.getByText("Add Cart")); // Önce ürünü sepete ekliyoruz.
  fireEvent.click(screen.getByText("Remove Cart")); // Sonra "Remove Cart" butonuna tıklıyoruz.
  expect(screen.getByText("Count: 0")).toBeInTheDocument(); // Sepetteki ürün sayısı 0 olmalıdır.
});

Tam Kod

// onursahin.net

import React from "react";
import { render, fireEvent, screen } from "@testing-library/react";
import ProductCard from "./App";

describe("ProductCard Component Testi", () => {
  it("Ürün kartı başarılı şekilde render edilmelidir", () => {
    // ProductCard bileşenini render ediyoruz.
    render(<ProductCard />);

    // Ürün bilgisi doğru mu?
    expect(screen.getByText("iPhone 15 Pro")).toBeInTheDocument(); // Ürün adı doğru bir şekilde "iPhone 15 Pro" olarak gösteriliyor mu?
    expect(screen.getByText("100")).toBeInTheDocument(); // Fiyat doğru bir şekilde 100 olarak gösteriliyor mu?

    // Ürün resmi doğru mu?
    const productImage = screen.getByAltText("iPhone 15 Pro"); 
    expect(productImage).toBeInTheDocument(); 
    expect(productImage.src).toBe(
      "https://onursahin.net/wp-content/uploads/2022/03/images.png"
    );
  });

  // "Add Cart" butonuna tıklanınca ürün sayısı artıyor mu?
  it("Add Cart butonuna tıklandığında ürünün sepete eklenmesi gerekmektedir", () => {
    render(<ProductCard />);
    fireEvent.click(screen.getByText("Add Cart")); // "Add Cart" butonuna tıklıyoruz.
    expect(screen.getByText("Count: 1")).toBeInTheDocument(); // Sepetteki ürün sayısı 1 olmalıdır.
  });

  // "Remove Cart" butonuna tıklanınca ürün sayısı sıfırlanıyor mu?
  it("Remove Cart butonuna tıklandığında ürünün sepetten kaldırılması gerekmektedir", () => {
    render(<ProductCard />);
    fireEvent.click(screen.getByText("Add Cart")); // Önce ürünü sepete ekliyoruz.
    fireEvent.click(screen.getByText("Remove Cart")); // Sonra "Remove Cart" butonuna tıklıyoruz.
    expect(screen.getByText("Count: 0")).toBeInTheDocument(); // Sepetteki ürün sayısı 0 olmalıdır.
  });
});

Sonuç:

  • Bonus

Snapshot Testi

Jest ile snapshot testi, bir componentin çıktısını yakalamanıza ve bunu aynı çıktının kayıtlı sürümüyle karşılaştırmanıza olanak sağlar. Bu, componentin çıktısında yapılan istenmeyen değişikliklerin tespit edilmesine yardımcı olur.

Jest’te snapshot testi oluşturmak için, test dosyanıza aşağıdaki kodu ekleyebilirsiniz;

it('ProductCard SnapShot Test', () => {
  const { asFragment } = render(<ProductCard />);
  expect(asFragment()).toMatchSnapshot();
});

  • İpuçları

Code Coverage Raporu Oluşturma

Jest, Code Coverage raporlamasıyla kod tabanınızın ne kadarının testlerle kapsandığını hızlı ve kolay bir şekilde değerlendirmenizi sağlar. Bu raporlar, kodunuzun hangi bölümlerinin test edildiğini kesin olarak göstermektedir.

npm test -- --coverage

Bu komut testlerinizi çalıştırır ve proje dizininde raporu oluşturur. Raporu görüntülemek için index.html dosyasını açabilirsiniz.

Test Hızını Arttırma

–maxWorkers=<num>, Jest testlerini daha hızlı çalıştırmak için kullanılmaktadır. Özellikle çok sayıda testiniz varsa ve test süresini azaltmak istiyorsanız, worker sayısını ayarlayarak performansı artırabilirsiniz. Jest, varsayılan olarak testleri yürütmek için birden fazla worker kullanır. Bu, testlerin daha hızlı çalışmasını sağlar. Varsayılan olarak, bu değer makinenizdeki çekirdek sayısına eşittir.

Ör: --maxWorkers=4 Jest’e en fazla 4 worker kullanması gerektiğini söyler. Bu, sistem kaynaklarına bağlı olarak ayarlanabilir. Daha fazla worker kullanmak, genellikle testlerin daha hızlı çalışmasını sağlar, ancak sisteminizdeki kaynaklarla dengeli olmalıdır.

npm test -- --maxWorkers=4