Selenium'da Otomasyon: Sayfa Nesne Modeli ve Sayfa Fabrikası

Yayınlanan: 2022-03-11

Otomatik testler yazmak, herhangi bir çevik yazılım geliştirme ekibi için bir lüksten daha fazlasıdır. Bu bir ihtiyaçtır ve yazılım geliştirme döngülerinin ilk aşamalarında hataları hızlı bir şekilde bulmak için gerekli bir araçtır. Hala geliştirme aşamasında olan yeni bir özellik olduğunda, geliştiriciler otomatik testler yapabilir ve sistemin diğer bölümlerinin bu değişikliklerden nasıl etkilendiğini görebilir. Bu makale, Selenium'da Sayfa Nesnesi modelini kullanarak otomatik testi nasıl hızlandırabileceğinizi açıklayacaktır.

Test otomasyonu sayesinde, hata düzeltme maliyetini düşürmek ve yazılım kalite güvencesi (QA) sürecine genel iyileştirme getirmek mümkündür. Uygun testlerle geliştiriciler, QA'ya ulaşmadan önce bile hataları bulma ve çözme şansı elde eder. Test otomasyonu ayrıca, sürekli gerileyen test senaryolarını ve özellikleri otomatikleştirmemize yardımcı olur. Bu şekilde QA'ların uygulamanın diğer bölümlerini test etmede daha fazla zamanı olur. Ayrıca bu, üretim sürümlerinde ürünün kalitesinin sağlanmasına yardımcı olur. Sonuç olarak, etkili bir şekilde daha kararlı ürünler ve daha verimli bir KG süreci elde ederiz.

Selenium otomasyonu, web uygulamaları için test otomasyonunu basitleştirir

Selenium, web uygulamaları için test otomasyonunu basitleştirir
Cıvıldamak

Otomatik testler yazmak geliştiriciler ve mühendisler için kolay bir iş gibi görünse de, herhangi bir çevik süreçte kötü uygulanan testler ve yüksek kod bakım maliyeti ile sonuçlanma olasılığı hala vardır. Herhangi bir çevik geliştirme projesinde sürekli olarak değişiklik veya özellik sunmaya çalışmak, testler söz konusu olduğunda maliyetli olabilir. 20 testin dayandığı bir web sayfasındaki bir öğeyi değiştirmek, birinin bu 20 test rutinini gözden geçirmesini ve her birini yeni tanıtılan bu değişikliğe uyum sağlamak için güncellemesini gerektirecektir. Bu sadece gerçekten zaman alıcı olmakla kalmaz, aynı zamanda otomatik testlerin erken uygulanması söz konusu olduğunda ciddi bir motivasyon kırıcı faktör olabilir.

Ancak, değişikliği yalnızca tek bir yerde yapabilir ve ilgili her test rutininin bunu kullanmasını sağlayabilirsek ne olur? Bu yazıda, Selenium'daki otomatik testlere ve bakımı yapılabilir ve yeniden kullanılabilir test rutinleri yazmak için Sayfa Nesnesi modellerini nasıl kullanabileceğimize bakacağız.

Selenyum'da Sayfa Nesne Modeli

Sayfa Nesnesi modeli, Web sayfalarının sınıflar olarak temsil edildiği ve sayfadaki çeşitli öğelerin sınıf üzerinde değişkenler olarak tanımlandığı Selenium'da bir nesne tasarım modelidir. Tüm olası kullanıcı etkileşimleri daha sonra sınıf üzerinde yöntemler olarak uygulanabilir:

 clickLoginButton(); setCredentials(user_name,user_password);

Sınıflarda iyi adlandırılmış yöntemlerin okunması kolay olduğundan, bu, hem okunabilir hem de gelecekte bakımı veya güncellenmesi daha kolay olan test rutinlerini uygulamanın zarif bir yolu olarak çalışır. Örneğin:

Page Object modelini desteklemek için Page Factory kullanıyoruz. Selenium'daki Sayfa Fabrikası, Sayfa Nesnesinin bir uzantısıdır ve çeşitli şekillerde kullanılabilir. Bu durumda, web sayfası sınıflarında veya Sayfa Nesnelerinde tanımlanan web öğelerini başlatmak için Sayfa Fabrikasını kullanacağız.

Web öğesi değişkenleri kullanılmadan önce, web öğeleri içeren Web sayfası sınıfları veya Sayfa Nesnelerinin Page Factory kullanılarak başlatılması gerekir. Bu, PageFactory'de initElements işlevinin kullanımıyla basitçe yapılabilir:

 LoginPage page = new LoginPage(driver); PageFactory.initElements(driver, page);

Veya daha da basit:

 LoginPage page = PageFactory.intElements(driver,LoginPage.class)

Veya web sayfası sınıfı yapıcısının içinde:

 public LoginPage(WebDriver driver) { this.driver = driver; PageFactory.initElements(driver, this); }

Page Factory, her WebElement değişkenini, yapılandırılmış "yer buluculara" dayalı olarak gerçek web sayfasındaki karşılık gelen bir öğeye referansla başlatır. Bu, @FindBy ek açıklamaları kullanılarak yapılır. Bu açıklama ile, onu tanımlamak için gerekli bilgilerle birlikte öğeyi aramak için bir strateji tanımlayabiliriz:

 @FindBy(how=How.NAME, using="username") private WebElement user_name;

Bu WebElement değişkeninde bir yöntem her çağrıldığında, sürücü önce onu geçerli sayfada bulur ve ardından etkileşimi simüle eder. Basit bir sayfa ile çalışıyorsak, onu her aradığımızda sayfadaki öğeyi bulacağımızı ve sonunda bu sayfadan ayrılacağımızı ve geri dönmeyeceğimizi biliyoruz, önbelleğe alabiliriz. başka bir basit açıklama kullanarak aranan alan:

 @FindBy(how=How.NAME, using="username") @CacheLookup private WebElement user_name;

WebElement değişkeninin bu tam tanımı, çok daha özlü biçimiyle değiştirilebilir:

 @FindBy(name="username") private WebElement user_name;

@FindBy ek açıklaması, işleri biraz daha kolaylaştıran bir dizi başka stratejiyi destekler:

 id, name, className, css, tagName, linkText, partialLinkText, xpath
 @FindBy() private WebElement user_name; @FindBy(name="passsword") private WebElement user_password; @FindBy(className="h3") private WebElement label; @FindBy(css=”#content”) private WebElement text;

Başlatıldıktan sonra, bu WebElement değişkenleri sayfadaki karşılık gelen öğelerle etkileşim kurmak için kullanılabilir. Aşağıdaki kod, örneğin:

 user_password.sendKeys(password);

… sayfadaki şifre alanına verilen tuş vuruşlarını gönderin ve şuna eşdeğerdir:

 driver.findElement(By.name(“user_password”)).sendKeys(password);

Devam edersek, genellikle bir sayfadaki öğelerin bir listesini bulmanız gereken durumlarla karşılaşırsınız ve işte o zaman @FindBys kullanışlı olur:

 @FindBys(@FindBy(css=”div[class='yt-lockup-tile yt-lockup-video']”))) private List<WebElement> videoElements;

Yukarıdaki kod, "yt-lockup-tile" ve "yt-lockup-video" olmak üzere iki sınıf adına sahip tüm div öğelerini bulacaktır. Bunu aşağıdakilerle değiştirerek daha da basitleştirebiliriz:

 @FindBy(how=How.CSS,using="div[class='yt-lockup-tile yt-lockup-video']") private List<WebElement> videoElements;

Ek olarak, verilen konumlandırıcılardan herhangi biriyle eşleşen öğeleri aramak için @ FindAll'ı birden çok @FindBy ek açıklamasıyla kullanabilirsiniz:

 @FindAll({@FindBy(how=How.ID, using=”username”), @FindBy(className=”username-field”)}) private WebElement user_name;

Artık web sayfalarını Java sınıfları olarak temsil edebileceğimize ve WebElement değişkenlerini kolayca başlatmak için Page Factory'yi kullanabileceğimize göre, Page Object desenini ve Page Factory'yi kullanarak basit Selenium testlerini nasıl yazabileceğimizi görmenin zamanı geldi.

Java'da Basit Selenyum Test Otomasyon Projesi

Sayfa Nesnesi modeli eğitimimiz için, geliştiricinin Toptal'a kaydolmasını otomatikleştirelim. Bunu yapmak için aşağıdaki adımları otomatikleştirmemiz gerekiyor:

  • www.toptal.com'u ziyaret edin

  • “Geliştirici Olarak Uygula” düğmesine tıklayın

  • Portal Sayfasında önce açılıp açılmadığını kontrol edin

  • “Toptal'a Katıl” düğmesine tıklayın

  • Formu doldur

  • "Toptal'a Katıl" butonuna tıklayarak formu gönderin

Proje Oluşturma

  • Java JDK'yı indirin ve yükleyin

  • InteliJ Idea'yı indirin ve yükleyin

  • Yeni bir Maven projesi oluşturun

  • “Project SDK”yı JDK'nıza bağlayın, örneğin: Windows'ta “C:\Program Files\Java\jdkxxx”

  • Grup kimliği ve yapı kimliği kurulumu:

 <groupId>SeleniumTEST</groupId> <artifactId>Test</artifactId>
  • Proje POM dosyanıza Selenium ve JUnit Maven bağımlılıkları ekleyin
 <dependencies> <!-- JUnit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <!-- Selenium --> <dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-firefox-driver</artifactId> <version>${selenium.version}</version> </dependency> <dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-support</artifactId> <version>${selenium.version}</version> </dependency> <dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-java</artifactId> <version>${selenium.version}</version> </dependency> </dependencies>

Selenium sürümünü ve JUnit Sürümünü, Google'da ve Selenium sitesinde JUnit Maven arayarak bulunabilecek en son sürüm numaralarıyla değiştirin.

Bu noktada, otomatik oluşturma etkinse, bağımlılıklar otomatik olarak indirilmeye başlamalıdır. Değilse, IntelliJ Idea IDE'nizin sağ tarafındaki Maven Projeleri panelinin altındaki Eklentiler > yükle > yükle: yükle'yi etkinleştirin.

selenyum testi öğretici IDE ekran görüntüsü

Proje önyüklendikten sonra “src/test/java” altında test paketimizi oluşturmaya başlayabiliriz. Pakete "com.toptal" adını verin ve altında iki paket daha oluşturun: "com.toptal.webpages" ve "com.toptal.tests".

selenyum testi öğretici ekran görüntüsü

Sayfa Nesnesi/Sayfa Fabrikası sınıflarımızı “com.toptal.webpages” altında ve test rutinlerini “com.toptal.tests” altında tutacağız.

Artık Sayfa Nesnesi sınıflarımızı oluşturmaya başlayabiliriz.

Ana Sayfa Sayfa Nesnesi

İlk uygulamamız gereken Toptal'ın ana sayfası (www.toptal.com). “com.toptal.webpages” altında bir sınıf oluşturun ve “Ana Sayfa” olarak adlandırın.

 package com.toptal.webpages; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.How; import org.openqa.selenium.support.PageFactory; public class HomePage { private WebDriver driver; //Page URL private static String PAGE_URL="https://www.toptal.com"; //Locators //Apply as Developer Button @FindBy(how = How.LINK_TEXT, using = "APPLY AS A DEVELOPER") private WebElement developerApplyButton; //Constructor public HomePage(WebDriver driver){ this.driver=driver; driver.get(PAGE_URL); //Initialise Elements PageFactory.initElements(driver, this); } public void clickOnDeveloperApplyButton(){ developerApplyButton.click(); } }

Eleman Konumlandırıcılarını Belirleme

Toptal'ın ana sayfasında özellikle bir unsurla ilgileniyoruz ve o da “Geliştirici Olarak Uygula” düğmesi. Bu öğeyi, yukarıda yaptığımız şey olan metni eşleştirerek bulabiliriz. Web sayfalarını Sayfa Nesnesi sınıfları olarak modellerken, öğeleri bulmak ve tanımlamak çoğu zaman bir angarya haline gelebilir. Google Chrome veya Firefox'un hata ayıklama araçlarıyla bu daha kolay hale getirilebilir. Bir sayfadaki herhangi bir öğeye sağ tıklayarak, öğe hakkında ayrıntılı bilgi edinmek için içerik menüsünden “Elemanı İncele” seçeneğini etkinleştirebilirsiniz.

Yaygın (ve benim tercih ettiğim) bir yol, Selenium'daki Firefox web sürücüsü ile birlikte Firefox'un FireBug uzantısını kullanarak öğeleri bulmaktır. FireBug eklentisini kurup etkinleştirdikten sonra, FireBug'u açmak için sayfaya sağ tıklayıp "FireBug ile öğeyi incele" seçeneğini seçebilirsiniz. FireBug'un HTML sekmesinden, sayfadaki herhangi bir öğenin XPath, CSS Yolu, Etiket adını veya "Kimliğini" (varsa) kopyalayabilirsiniz.

selenyumda sayfa nesne modeli: eleman bulucuları belirleme

Yukarıdaki ekran görüntüsündeki öğenin XPath'ini kopyalayarak, Sayfa Nesnemizde aşağıdaki gibi bir WebElement alanı oluşturabiliriz:

 @FindBy(xpath = "/html/body/div[1]/div/div/header/div/h1") WebElement heading;

Veya işleri basitleştirmek için ilgilendiğimiz öğeyi benzersiz bir şekilde tanımladığı sürece burada "h1" etiket adını kullanabiliriz:

 @FindBy(tagName = "h1") WebElement heading;

DeveloperPortalPage Sayfa Nesnesi

Ardından, “Geliştirici Olarak Uygula” düğmesine tıklayarak ulaşabileceğimiz geliştirici portalı sayfasını temsil eden bir Sayfa Nesnesine ihtiyacımız var.

Bu sayfada, iki ilgi unsurumuz var. Sayfanın yüklenip yüklenmediğini belirlemek için başlığın varlığını doğrulamak istiyoruz. Ayrıca “Toptal'a Katıl” düğmesi için bir WebElement alanı istiyoruz.

 package com.toptal.webpages; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.PageFactory; public class DeveloperPortalPage { private WebDriver driver; @FindBy(xpath = "/html/body/div[1]/div/div/header/div/h1") private WebElement heading; @FindBy(linkText = "JOIN TOPTAL") private WebElement joinToptalButton; //Constructor public DeveloperPortalPage (WebDriver driver){ this.driver=driver; //Initialise Elements PageFactory.initElements(driver, this); } //We will use this boolean for assertion. To check if page is opened public boolean isPageOpened(){ return heading.getText().toString().contains("Developer portal"); } public void clikOnJoin(){ joinToptalButton.click(); } }

DeveloperApplyPage Sayfa Nesnesi

Ve son olarak, bu proje için üçüncü ve son sayfa nesnemiz için, geliştirici başvuru formunu içeren sayfayı temsil eden birini tanımlıyoruz. Burada birkaç form alanıyla uğraşmak zorunda olduğumuz için her form alanı için bir WebElement değişkeni tanımlıyoruz. Her alanı “id”lerine göre buluyoruz ve ilgili alanlar için tuş vuruşlarını simüle eden her alan için özel ayarlayıcı yöntemler tanımlıyoruz.

 package com.toptal.webpages; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.PageFactory; public class DeveloperApplyPage { private WebDriver driver; @FindBy(tagName = "h1") WebElement heading; @FindBy() WebElement developer_email; @FindBy() WebElement developer_password; @FindBy() WebElement developer_password_confirmation; @FindBy() WebElement developer_full_name; @FindBy() WebElement developer_skype; @FindBy() WebElement join_toptal_button; //Constructor public DeveloperApplyPage(WebDriver driver){ this.driver=driver; //Initialise Elements PageFactory.initElements(driver, this); } public void setDeveloper_email(String email){ developer_email.clear(); developer_email.sendKeys(email); } public void setDeveloper_password(String password){ developer_password.clear(); developer_password.sendKeys(password); } public void setDeveloper_password_confirmation(String password_confirmation){ developer_password_confirmation.clear(); developer_password_confirmation.sendKeys(password_confirmation); } public void setDeveloper_full_name (String fullname){ developer_full_name.clear(); developer_full_name.sendKeys(fullname); } public void setDeveloper_skype (String skype){ developer_skype.clear(); developer_skype.sendKeys(skype); } public void clickOnJoin(){ join_toptal_button.click(); } public boolean isPageOpened(){ //Assertion return heading.getText().toString().contains("Apply to join our network as a developer"); } }

Basit Bir Selenyum Testi Yazma

Sayfalarımızı temsil eden Sayfa Nesnesi sınıfları ve yöntemleri olarak kullanıcı etkileşimleri ile artık basit test rutinimizi bir dizi basit yöntem çağrısı ve iddiası olarak yazabiliriz.

 package com.toptal.tests; import com.toptal.webpages.DeveloperApplyPage; import com.toptal.webpages.DeveloperPortalPage; import com.toptal.webpages.HomePage; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.openqa.selenium.WebDriver; import org.openqa.selenium.firefox.FirefoxDriver; import java.net.URL; import java.util.concurrent.TimeUnit; public class ApplyAsDeveloperTest { WebDriver driver; @Before public void setup(){ //use FF Driver driver = new FirefoxDriver(); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); } @Test public void applyAsDeveloper() { //Create object of HomePage Class HomePage home = new HomePage(driver); home.clickOnDeveloperApplyButton(); //Create object of DeveloperPortalPage DeveloperPortalPage devportal= new DeveloperPortalPage(driver); //Check if page is opened Assert.assertTrue(devportal.isPageOpened()); //Click on Join Toptal devportal.clikOnJoin(); //Create object of DeveloperApplyPage DeveloperApplyPage applyPage =new DeveloperApplyPage(driver); //Check if page is opened Assert.assertTrue(applyPage.isPageOpened()); //Fill up data applyPage.setDeveloper_email("[email protected]"); applyPage.setDeveloper_full_name("Dejan Zivanovic Automated Test"); applyPage.setDeveloper_password("password123"); applyPage.setDeveloper_password_confirmation("password123"); applyPage.setDeveloper_skype("automated_test_skype"); //Click on join //applyPage.clickOnJoin(); } @After public void close(){ driver.close(); } }

Testi Çalıştırma

Bu noktada proje yapınız şöyle görünmelidir:

selenyum testi örneği

Testi çalıştırmak istiyorsanız, ağaçtan “ApplyAsDeveloperTest” öğesini seçin, üzerine sağ tıklayın ve ardından Run 'ApplyAsDeveloperTest' öğesini seçin.

selenyum testi örneği

Test çalıştırıldıktan sonra, sonuçları IDE'nizin sol alt köşesinde görebilirsiniz:

selenyum testi örneği

Çözüm

Sayfa Nesnesi ve Sayfa Fabrikası, Selenium'da web sayfalarını modellemeyi ve bunları otomatik olarak test etmeyi kolaylaştırır ve hem geliştiricilerin hem de QA'ların yaşamını çok daha basit hale getirir. Doğru yapıldığında, bu Sayfa Nesnesi sınıfları tüm test takımınızda yeniden kullanılabilir ve kendinize, çevik geliştirmeden ödün vermeden projeleriniz için erkenden otomatik Selenium testleri uygulama fırsatı verir. Sayfa nesnesi modellerinizdeki kullanıcı etkileşimlerini soyutlayarak ve test rutinlerinizi hafif ve basit tutarak, test takımınızı çok az çabayla değişen gereksinimlere uyarlayabilirsiniz.

Umarım size bakımı kolay, güzel ve temiz test kodunun nasıl yazılacağını göstermeyi başardım. Makaleyi en sevdiğim QA alıntısıyla bitireceğim:

İki kez düşünün, bir kez kodlayın!

İlgili: Başsız Tarayıcı ile Web Kazıma: Bir Kuklacı Eğitimi