Selenium& Java : Page Object Model — Page Factory Kullanımı

Pınar Örmeci
Sahibinden Technology
5 min readApr 7, 2022

Merhabalar,

Test otomasyon projelerinde kullandığımız page object model nedir, neden ihtiyaç duyarız gibi soruların cevaplarını bu yazı ile sizlere anlatmaya çalışacağım.

Page Object Model

Page object model (POM), test otomasyon projelerinde kullanımı çok yaygın olan bir design pattern’ dır.

POM sayesinde kod tekrarı yapmayız ve kod maintenance çok daha kolay olur. Page object model ile her sayfayı, bir page class’ı ile ilişkilendiririz. Bu page classında da o sayfaya ait olan web elementler ve yine o sayfaya ait metodlar yer alır. Böylece, bu sayfada herhangi bir elementin locator’ında değişiklik olduğu zaman, bunu ortak bir yerden yönetebiliriz. Bu sayfada işlem yapan her testimizde element locator’unu tek tek değiştirmek yerine, tek bir class’ta yapmış olduğumuz değişiklik ile maintenance çok daha kolay hale gelir.

Bunu bir örnek ile inceleyelim:

sahibinden.com sitesi için bazı login senaryolarını düşünürsek,

Bu 3 case içinde yapmamız gereken ortak işlemler mevcut.

Testlerimizi page object model kullanmadan yazalım :

Boş kullanıcı adı/şifre — pom kullanmadan
Başarılı login — pom kullanmadan

Örneklerde gördüğümüz gibi, testlerimizde ilk yaptığımız, işlem yapacağımız web elementini bulmak ve daha sonra gerekli işlemi yapmak.

Farklı test caselerine göre, aynı element ile birden çok test metodu içinde işlem yapılabilir. Bu elementin locator’ı değiştiği zaman ise kullanmış olduğumuz tüm test caselerine gidip teker teker değiştirmemiz gerekecek.

Yukarıdaki örnekte submitBtn elemanının id’sinin değiştiği bir dünyada bizim yazdığımız testlerde bu path değişikliğini düzenlememiz gerekli. Değilse testlerimiz fail eder. Mevcut örneğimizde sadece 3 test metodumuz olmasına rağmen 3 kere aynı işlemi yapacak olmak gereksiz maliyet. Büyük projelerde ise bu tarz durumlar ile karşılaştığımız zaman onlarca classın içinde elemanları arayıp bulmak zorunda kalabiliriz.

Gördüğümüz gibi, page object model olmadan testlerimizi yönetmek istediğimiz zaman çok daha fazla iş gücü harcıyoruz.

Yukarıdaki örneği pom ile yapıyor olsaydık yapımız aşağıdaki şekle benzeyecekti.

Peki POM bize neler sağlar ?

🔹 ️Örneğimizde gördüğümüz gibi, kod tekrarı yapmaktan alıkoyar.

🔹 Testlerimizin bulunduğu sınıf ve elemanlarımızın olduğu sınıf ayrıdır. Değişiklik olduğu zaman, tekrar eden elemanlarımız olmadığı için kod yönetimimiz kolaylaşır ve değişikliklere çok daha kolay adapte olabiliriz.

🔹 Metod isimlerimiz kullanıcının arayüzde yaptığı işlem ile uyumlu olmalıdır. Böylece kodumuz daha anlaşılır olur.

🔹 Kodu yeniden kullanılabilir hale getirir. Örneğin birden fazla test metodumuz aynı elemanları kullanıyorsa her birinde bu elemanı tekrar tekrar elde etmemize gerek kalmaz, bir page class’ında bu elemanı tanımladığımız için, ileride bu elemanı kullanacak test metodları içinde kolaylık sağlanmış olur.

POM Örnek Uygulama

Bir maven projesi oluşturalım ve gerekli dependency’ leri ekleyelim(selenium, junit).

👉 Testlerimizi POM kullanarak yazmaya başlayabiliriz!

Her bir sayfa için ayrı page classı oluşturduktan sonra projemizin yapısı şu şekilde olacak :

POM’a göre proje yapısı

Devam etmeden önce POM uygularken kullandığımız Page Factory tekniğinden de bahsetmek istiyorum.

Page Factory, page object model uygulamanın bir yoludur. Page Factory kullanmamız için selenium webdriver, PageFactory class ını bizlere sunar ve böylece @FindBy anotasyonu dünyamıza girer. Page içerisinde bulunan her bir web elementi bu anotasyon ile page classımızda belirtilir. @FindBy kullanarak, elemanları findElement/s ile bulmamıza gerek kalmaz ki bu da bize sağladığı yararlardan biridir. Page Factory classının bizlere sağladığı bir diğer metod ise initElements metodudur ki bu metod ile sayfada bulunan web elementleri initialize edilir. Eğer istenen web elementi DOM üzerinde yoksa, noSuchElementException Selenium exception fırlatılır.

Şimdi yukarıda yapmış olduğumuz login case örneğini bir de POM ve page factory kullanarak yapalım. Böylece aslında bu design pattern ı kullandığımız zaman kodun ne kadar sade, maintain etmesi kolay ve okunabilir olduğunu görelim.

Tüm sayfalarımızda initElements metodunu kullanacağımız için bir BasePage oluşturup sayfa hiyerarşisini şu şekilde yapabiliriz :

Page Factory kullanımı ile artık sayfadaki elementleri tanımlamamız daha kolay. Bu yapı ile yapmamız gereken, page içerisinde elementleri tanımlamak ve bu elementlere ait etkileşim sağlayacak metodları yazmak ki sayfada işlemler yapabilelim.

İlk örneğimizde bir web elementini bulmak için şu şekilde bir tanımlama yapmıştık.

WebElement userName = driver.findElement(By.id("username"));

Şimdi ise LoginPage class ımızın içinde @FindBy ile elementimizi ifade edebilir ve By ile kullandığımız css, xpath, id gibi çeşitli locator ları da kullanabiliriz.

@FindBy(id = "username")
private WebElement usernameTextBox;

Elementi private yapmamızın amacı, bu elemente ilgili class haricinden erişilmesini istemememiz. Çünkü biz page içinde olan elementlere direkt erişmek yerine, onların bağlı olduğu metodları kullanacağız.

Örneğin login işlemi için bir login metodu yazarsak :

public <T extends BasePage> T login(T page, String username, String password)
{
usernameTextBox.sendKeys(username);
passwordTextBox.sendKeys(password);
submitBtn.click();
return page;
}

Burada önemli olan bir diğer nokta da yazmış olduğumuz metodların ilgili sayfayı döndürüyor olması. Yani biz login işlemini başarılı bir şekilde gerçekleştiremezsek, kullanıcı yine login sayfasında kalacak ve bir uyarı mesajı görecek. Burada Login sayfasının return etmesi gerekli. Ancak başarılı login işlemi sonrasında ise kullanıcı artık login sayfasından ayrılıp bana özel sayfasına gitmeli. Bu durumda return edeceği sayfa farklı olmalı. Bu sebeple generic bir return type kullandık.

Login page şu şekilde görünecek:

Şimdi de testimizi yazalım.

Pom ve Page factory ile örnek test

Testimiz hazır. Gördüğünüz gibi ne kadar kısa ve okunabilir bir şekilde tamamlamış olduk. Login sayfasında herhangi bir elemanın değişiminde de kullandığımız her bir yerde ayrı ayrı değişiklik yapmak yerine tek bir yerden yönetebiliriz. Dönüş tipi birbiri ile aynı olan metodlarda da chain şekilde kullanım yapılabilir.

chain metod kullanımı

Umarım faydalı olmuştur. Başka yazılarda görüşmek üzere!

Örnek ile ilgili github linki : https://github.com/PinarOrmeci/MediumPOMPageFactory

--

--