ViraStack
  • Akademi
  • Hakkında
  • Destek
Genel BakışKaynaklarKatkı
ViraStack

Frontend ekosistemi: ücretsiz rehberler, proje şablonları, AI kuralları ve form bileşenleri.

Ürünler

  • ViraStack Start
  • ViraStack AI
  • ViraStack Mask
  • ViraStack Password
  • ViraStack Guide

Keşfet

  • Akademi
  • Hakkında
  • Marka
  • Destek

© 2026 ViraStack.

Açık kaynak · MIT

Playwright

05 / 10

Page Object

Locator'ları ve akışları sayfa nesnelerinde toplamak, Page Object'e ne konur ne konmaz, assertion tartışması, bileşen nesneleri ve aşırı soyutlamadan kaçınmak.

Sorun: Tekrar Eden Locator'lar

Giriş akışını test eden on test düşünün. Her biri e-posta alanını, parola alanını ve butonu kendisi bulur. Buton metni "Giriş yap"tan "Oturum aç"a değişince on dosyayı düzeltirsiniz.

Page Object bu tekrarı bir sınıfta toplar. Playwright dokümanı iki faydasını sayar: uygulamanıza uygun, üst seviye bir API ile testi yazmayı kolaylaştırır; locator'ları tek yerde toplayarak bakımı kolaylaştırır.1

Martin Fowler kalıbın amacını şöyle anlatır: Page Object, bir insanın sayfada yapabildiği ve görebildiği her şeyi test koduna sunar, alttaki HTML ayrıntısını gizler. Test "e-posta alanına yaz" der; alanın nasıl bulunduğunu bilmez.2

İlk Page Object

// tests/pages/login-page.ts
import type { Locator, Page } from "@playwright/test";

export class LoginPage {
  readonly email: Locator;
  readonly password: Locator;
  readonly submit: Locator;
  readonly error: Locator;

  constructor(private readonly page: Page) {
    const form = page.getByRole("form", { name: "Giriş" });
    this.email = form.getByLabel("E-posta");
    this.password = form.getByLabel("Parola");
    this.submit = form.getByRole("button", { name: "Giriş yap" });
    this.error = form.getByRole("alert");
  }

  async goto() {
    await this.page.goto("/login");
  }

  async login(email: string, password = "parola123") {
    await this.email.fill(email);
    await this.password.fill(password);
    await this.submit.click();
  }
}

İki tür üye var:

  • Locator alanları (email, error): testin doğrulayacağı ya da tek başına kullanacağı elementler. Locator oluşturmak sayfaya dokunmadığı için constructor'da tanımlamak güvenlidir (bkz. İlk test ve locator'lar).

  • Eylem metodları (goto, login): birkaç adımdan oluşan, kullanıcının diliyle adlandırılmış akışlar.

Test artık niyeti okur:

// tests/login.spec.ts
import { test, expect } from "@playwright/test";
import { LoginPage } from "./pages/login-page";

test("hatalı parola hata mesajı gösterir ve e-postayı korur", async ({ page }) => {
  const loginPage = new LoginPage(page);
  await loginPage.goto();
  await loginPage.login("yonetici@example.com", "yanlis");

  await expect(loginPage.error).toHaveText("E-posta veya parola hatalı.");
  await expect(loginPage.email).toHaveValue("yonetici@example.com");
});

Satıra ve Listeye Metod

Tabloda belirli bir satır gibi parametreli elementler için locator döndüren bir metod yazın:

// tests/pages/orders-page.ts
export class OrdersPage {
  readonly table: Locator;
  readonly rows: Locator;
  readonly statusFilter: Locator;

  constructor(private readonly page: Page) {
    this.table = page.getByRole("table", { name: "Sipariş listesi" });
    this.rows = this.table.getByRole("row").filter({ has: page.getByRole("cell") });
    this.statusFilter = page.getByLabel("Durum");
  }

  row(orderId: string) {
    return this.rows.filter({ hasText: orderId });
  }

  async filterBy(label: string) {
    await this.statusFilter.selectOption({ label });
  }

  async cancel(orderId: string) {
    await this.row(orderId).getByRole("button", { name: "İptal et" }).click();
  }
}

row("SP-1001") hem eylemde (cancel) hem assertion'da kullanılır:

await expect(ordersPage.row("SP-1001")).toContainText("İptal edildi");

Assertion Page Object'e Girer mi?

İki görüş var.

Martin Fowler Page Object'in assertion yapmamasını savunur. Görevi sayfanın durumunu sunmaktır; doğrulama testin işidir. Tek istisna, sayfanın her zaman doğru olması gereken bir değişmezini kontrol etmektir.2 Playwright dokümanının örneğinde ise bir eylem metodu expect ile bir sonraki sayfanın açıldığını doğrular.1

Pratik bir ayrım:

Page Object'eTeste
Eylemin tamamlandığını beklemek (sonraki sayfa geldi mi)Testin asıl iddiası (mesaj doğru mu, satır iptal edildi mi)
Locator ve eylemSenaryoya özel beklenen değerler

Testi okuyan kişi neyin doğrulandığını Page Object'e girmeden görebilmelidir. "Asıl iddia testte" kuralı bunu sağlar.

Sayfa Değil, Anlamlı Parça

Adına rağmen Page Object sayfayla birebir eşleşmek zorunda değildir. Martin Fowler sayfadaki anlamlı parçalar için nesne yazmayı önerir: bir albüm listesi sayfası birkaç albüm nesnesi, bir üst bilgi ve bir alt bilgi nesnesi içerebilir.2 Her sayfada tekrar eden bir gezinme menüsü ya da bir tarih seçici kendi nesnesini hak eder:

export class DatePicker {
  constructor(private readonly root: Locator) {}

  async pick(day: number) {
    await this.root.getByRole("button", { name: "Takvimi aç" }).click();
    await this.root.getByRole("gridcell", { name: String(day), exact: true }).click();
  }
}

Kök bir Locator alan nesne sayfanın neresinde olursa olsun çalışır: new DatePicker(page.getByRole("group", { name: "Teslim tarihi" })).

Aşırı Soyutlamadan Kaçının

Page Object bir araçtır, hedef değil. Sık görülen hatalar:

  • Her elemente metod: clickSubmitButton(), getEmailInput(). Locator alanını açın; loginPage.submit.click() yeterince okunur.

  • Tek kullanımlık akışlar: Yalnızca bir testte geçen adımı Page Object'e taşımak tekrar azaltmaz, sadece testi okumayı zorlaştırır.

  • Locator'ı gizleyip boolean döndürmek: isErrorVisible(): Promise<boolean> web-first assertion'ın beklemesini kaybettirir (bkz. Assertion ve bekleme). Locator döndürün, testte expect ile doğrulayın.

Playwright dokümanı da basit testlerde biraz tekrarın kabul edilebilir olduğunu, okunurluğu artırıyorsa tercih edilebileceğini söyler.3

İpucu

Playwright dokümanının Page Object örneği locator'ları page.locator("a", { hasText: "Get started" }) ve CSS seçicilerle yazar. Kalıbı oradan öğrenin, locator'ları bu rehberdeki gibi getByRole ve getByLabel ile yazın.1

Her Testte new Yazmamak

Her testin başında new LoginPage(page) yazmak da bir tekrardır. Bir sonraki derste Page Object'leri fixture olarak vereceğiz; test parametresinde hazır gelecekler:

test("hatalı parola", async ({ loginPage }) => {
  await loginPage.goto();
});

Kendin Dene

  • Giriş testlerinizdeki locator'ları bir LoginPage sınıfına taşıyın. Buton metnini değiştirip kaç dosyayı düzeltmeniz gerektiğine bakın.

  • Bir tablo için row(id) metodu yazın ve hem bir eylemde hem bir assertion'da kullanın.

  • Sayfanızda tekrar eden bir parça bulun (menü, arama kutusu) ve kök Locator alan bir bileşen nesnesi yazın.

  • Page Object'lerinizdeki Promise<boolean> döndüren metodları bulun ve locator döndürecek şekilde değiştirin.

Detaylı Öğrenmek İçin

  • Resmi doküman: Playwright, "Page object models"; Playwright'ta kalıbın uygulanışı.1

  • Yazı: Martin Fowler, "Page Object"; kalıbın amacı, assertion tartışması ve parçalara bölmek.2

Kaynaklar

  • 1DokümanPlaywright: Page object models

    Page Object sınıfı, locator alanları ve testte kullanımı.

  • 2MakaleMartin Fowler

    : — 10 Eylül 2013. Kalıbın amacı, assertion'ların yeri, parçalara bölmek ve başka Page Object döndürmek.

  • 3DokümanPlaywright: Best Practices

    Test izolasyonu ve basit testlerde tekrarın kabul edilebilirliği.

Bu sayfayı düzenle

Son güncelleme tarihi: 22 Ekim 2026

Önceki adım04. Trace ile hata ayıklamaSonraki adım06. Auth ve fixture