Selenium’da findElement ve findElements Metotları: Kapsamlı Bir Rehber ve Örnekler
Web otomasyon testlerinde ve veri kazıma (web scraping) işlemlerinde Selenium WebDriver, web sayfalarıyla etkileşim kurmak için vazgeçilmez bir araçtır. Selenium’ın gücünün temelinde, web sayfasındaki belirli elementleri bulma ve onlarla etkileşim kurma yeteneği yatar. Bu yetenek, özellikle findElement() ve findElements() metotları aracılığıyla sağlanır. Bu makale, bu iki kritik metodu, aralarındaki farkları, nasıl kullanılacaklarını ve en iyi uygulama yöntemlerini detaylı örneklerle ele alacaktır.
Selenium WebDriver ve Web Elementleri
Selenium WebDriver, tarayıcılarla doğrudan etkileşim kurarak web uygulamalarını otomatikleştiren bir API setidir. Bir web sayfası, metin kutuları, düğmeler, bağlantılar, resimler, tablolar ve daha fazlası gibi çeşitli web elementlerinden oluşur. Selenium ile bu elementleri bulmak, tıklamak, metin girmek, özelliklerini okumak gibi işlemler gerçekleştirebiliriz. Elementleri bulmak için kullanılan anahtar kavram ise “locator”lardır (konumlandırıcılar).
Locator’lar (Konumlandırıcılar): Web Elementlerini Bulmanın Anahtarı
Bir web sayfasındaki elementleri benzersiz bir şekilde tanımlamak için çeşitli stratejiler kullanılır. Bu stratejilere locator denir. Selenium, elementleri bulmak için aşağıdaki yaygın locator türlerini destekler:
id
Bir elementin HTML içinde benzersiz bir id niteliği varsa, bu en güvenilir ve hızlı locator’dır. HTML standartlarına göre id değerleri sayfa içinde benzersiz olmalıdır.
// Örnek HTML:
WebElement usernameField = driver.findElement(By.id("username"));
name
Elementin name niteliğini kullanarak bulur. Genellikle form elementleri için kullanılır.
// Örnek HTML:
WebElement passwordField = driver.findElement(By.name("sifre"));
className
Elementin class niteliğini kullanarak bulur. Birden fazla element aynı sınıfa sahip olabilir, bu yüzden findElement() kullanıldığında ilk eşleşen element döndürülür.
// Örnek HTML:
tagName
Elementin HTML etiket adını kullanarak bulur (örn. ,
). Genellikle findElements() ile belirli bir türdeki tüm elementleri toplamak için kullanılır.
// Örnek HTML: Link
WebElement firstLink = driver.findElement(By.tagName("a"));
linkText
Sadece (bağlantı) elementleri için kullanılır. Bağlantının tam görünen metnini eşleştirir.
// Örnek HTML: Hakkımızda
WebElement aboutLink = driver.findElement(By.linkText("Hakkımızda"));
partialLinkText
Yine sadece elementleri için kullanılır, ancak bağlantının görünen metninin bir kısmını eşleştirir.
// Örnek HTML: Bize Ulaşın
WebElement contactLink = driver.findElement(By.partialLinkText("Ulaşın"));
cssSelector
CSS seçicilerini kullanarak elementleri bulur. Oldukça güçlü ve esnektir, genellikle XPath’ten daha hızlıdır ve okunabilirliği daha iyidir.
// ID ile: #username
// Class ile: .btn-primary
// Tag ve class ile: input.input-field
// Nitelik ile: input[name='sifre']
WebElement usernameField = driver.findElement(By.cssSelector("#username"));
WebElement loginButton = driver.findElement(By.cssSelector(".btn-primary"));
xpath
XML Path Language (XPath) kullanarak elementleri bulur. En güçlü ve esnek locator’dır, ancak karmaşık XPath ifadeleri okunması ve bakımı zor olabilir. Hem mutlak (absolute) hem de göreceli (relative) yollarla kullanılabilir.
// Mutlak XPath (genellikle önerilmez): /html/body/div[1]/input[1]
// Göreceli XPath: //input[@id='username']
// Nitelik içeren: //button[text()='Giriş Yap']
WebElement usernameField = driver.findElement(By.xpath("//input[@id='username']"));
WebElement loginButton = driver.findElement(By.xpath("//button[text()='Giriş Yap']"));
Doğru locator’ı seçmek, testlerinizin sağlamlığı ve performansı için kritik öneme sahiptir. Genellikle id, ardından name, cssSelector ve son olarak xpath tercih edilir.
findElement() Metodu: Tek Bir Elementi Bulma
findElement() metodu, web sayfasında belirtilen locator stratejisine uyan ilk web elementini bulmak ve döndürmek için kullanılır. Eğer hiçbir element bulunamazsa, bu metod bir NoSuchElementException fırlatır.
Kullanım Amacı
- Belirli bir düğmeye tıklamak.
- Bir metin kutusuna veri girmek.
- Bir elementin metnini veya niteliğini okumak.
- Bir elementin varlığını doğrulamak (hata yakalama ile birlikte).
Sözdizimi (Syntax)
WebElement element = driver.findElement(By.locatorStrategy("locatorValue"));
Dönüş Tipi
findElement() metodu, bulunan web elementini temsil eden bir WebElement nesnesi döndürür.
Örnek Senaryo ve Kod
Hayali bir HTML sayfamız olduğunu varsayalım:
Test Sayfası
Selenium Test Başlığı
Bu bir giriş paragrafıdır.
Hakkımızda
İletişim
Ürünler
Ürün 1
Açıklama 1
Ürün 2
Açıklama 2
Bu sayfadaki elementleri findElement() kullanarak bulalım:
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.NoSuchElementException; // Hata yakalama için
public class FindElementExamples {
public static void main(String[] args) {
// WebDriver'ı başlatma (Chrome için)
// System.setProperty("webdriver.chrome.driver", "/path/to/chromedriver"); // Kendi chromedriver yolunuzu belirtin
WebDriver driver = new ChromeDriver();
driver.manage().window().maximize();
// Test edilecek HTML dosyasını açma (yerel dosya veya bir URL olabilir)
// Gerçek bir senaryoda bir URL açarsınız: driver.get("https://www.example.com");
driver.get("file:///C:/Users/YourUser/Desktop/test_page.html"); // Kendi dosya yolunuzu belirtin
try {
// 1. By.id ile element bulma
WebElement mainHeader = driver.findElement(By.id("mainHeader"));
System.out.println("Ana Başlık Metni (ID): " + mainHeader.getText());
// 2. By.name ile element bulma
WebElement usernameField = driver.findElement(By.name("kullaniciAdi"));
usernameField.sendKeys("testKullanici");
System.out.println("Kullanıcı Adı alanına metin girildi.");
// 3. By.className ile element bulma
WebElement loginButton = driver.findElement(By.className("btn-primary"));
System.out.println("Giriş Düğmesi Metni (Class Name): " + loginButton.getText());
// loginButton.click(); // Düğmeye tıklama işlemi
// 4. By.tagName ile element bulma (ilk h1 elementi)
WebElement firstH1 = driver.findElement(By.tagName("h1"));
System.out.println("İlk H1 Etiketi Metni (Tag Name): " + firstH1.getText());
// 5. By.linkText ile element bulma
WebElement aboutLink = driver.findElement(By.linkText("Hakkımızda"));
System.out.println("Hakkımızda Bağlantısı Metni (Link Text): " + aboutLink.getText());
// 6. By.partialLinkText ile element bulma
WebElement contactLink = driver.findElement(By.partialLinkText("İletişim"));
System.out.println("İletişim Bağlantısı Metni (Partial Link Text): " + contactLink.getText());
// 7. By.cssSelector ile element bulma
WebElement passwordField = driver.findElement(By.cssSelector("input[name='sifre']"));
passwordField.sendKeys("gizliSifre");
System.out.println("Şifre alanına metin girildi (CSS Selector).");
WebElement introParagraph = driver.findElement(By.cssSelector("p.intro-paragraph"));
System.out.println("Giriş Paragrafı Metni (CSS Selector): " + introParagraph.getText());
// 8. By.xpath ile element bulma
WebElement product1Header = driver.findElement(By.xpath("//div[@class='product-item']/h3[text()='Ürün 1']"));
System.out.println("Ürün 1 Başlığı Metni (XPath): " + product1Header.getText());
// Var olmayan bir elementi bulmaya çalışma (NoSuchElementException fırlatır)
try {
WebElement nonExistentElement = driver.findElement(By.id("nonExistent"));
System.out.println("Bulunan element: " + nonExistentElement.getText());
} catch (NoSuchElementException e) {
System.out.println("Hata: 'nonExistent' ID'sine sahip element bulunamadı. (Beklenen hata)");
}
} catch (NoSuchElementException e) {
System.err.println("Bir element bulunamadı: " + e.getMessage());
} finally {
// Tarayıcıyı kapatma
driver.quit();
}
}
}
findElements() Metodu: Birden Fazla Elementi Bulma
findElements() metodu, web sayfasında belirtilen locator stratejisine uyan tüm web elementlerini bulmak ve bir liste olarak döndürmek için kullanılır. Eğer hiçbir element bulunamazsa, bu metod bir NoSuchElementException fırlatmaz; bunun yerine boş bir List döndürür. Bu, findElement() ile arasındaki en önemli farklardan biridir.
Kullanım Amacı
- Bir sayfadaki tüm bağlantıları toplamak.
- Bir tablodaki tüm satırları veya hücreleri almak.
- Belirli bir sınıfa sahip tüm elementleri işlemek.
- Dinamik olarak oluşturulan element gruplarını yönetmek.
Sözdizimi (Syntax)
List elements = driver.findElements(By.locatorStrategy("locatorValue"));
Dönüş Tipi
findElements() metodu, WebElement nesnelerinden oluşan bir List döndürür.
Örnek Senaryo ve Kod
Yukarıdaki aynı hayali HTML sayfasını kullanarak findElements() ile birden fazla elementi bulalım:
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import java.util.List;
public class FindElementsExamples {
public static void main(String[] args) {
// WebDriver'ı başlatma (Chrome için)
// System.setProperty("webdriver.chrome.driver", "/path/to/chromedriver"); // Kendi chromedriver yolunuzu belirtin
WebDriver driver = new ChromeDriver();
driver.manage().window().maximize();
// Test edilecek HTML dosyasını açma
driver.get("file:///C:/Users/YourUser/Desktop/test_page.html"); // Kendi dosya yolunuzu belirtin
try {
// 1. By.tagName ile tüm bağlantıları bulma
List allLinks = driver.findElements(By.tagName("a"));
System.out.println("\n--- Tüm Bağlantılar (Tag Name: a) ---");
if (allLinks.isEmpty()) {
System.out.println("Sayfada hiç bağlantı bulunamadı.");
} else {
System.out.println("Bulunan bağlantı sayısı: " + allLinks.size());
for (WebElement link : allLinks) {
System.out.println(" Metin: " + link.getText() + ", URL: " + link.getAttribute("href"));
}
}
// 2. By.className ile belirli bir sınıfa sahip tüm elementleri bulma
List navLinks = driver.findElements(By.className("nav-link"));
System.out.println("\n--- Navigasyon Bağlantıları (Class Name: nav-link) ---");
if (navLinks.isEmpty()) {
System.out.println("Sayfada 'nav-link' sınıfına sahip element bulunamadı.");
} else {
System.out.println("Bulunan navigasyon bağlantısı sayısı: " + navLinks.size());
for (WebElement link : navLinks) {
System.out.println(" Metin: " + link.getText());
}
}
// 3. By.cssSelector ile tüm ürün öğelerini bulma
List productItems = driver.findElements(By.cssSelector(".product-item"));
System.out.println("\n--- Ürün Öğeleri (CSS Selector: .product-item) ---");
if (productItems.isEmpty()) {
System.out.println("Sayfada hiç ürün öğesi bulunamadı.");
} else {
System.out.println("Bulunan ürün öğesi sayısı: " + productItems.size());
for (int i = 0; i < productItems.size(); i++) {
WebElement item = productItems.get(i);
// Ürün başlığını ve açıklamasını bulma (element içinden findElement)
WebElement title = item.findElement(By.tagName("h3"));
WebElement description = item.findElement(By.tagName("p"));
System.out.println(" Ürün " + (i + 1) + ": Başlık: " + title.getText() + ", Açıklama: " + description.getText());
}
}
// 4. By.xpath ile tüm H3 başlıklarını bulma
List allH3s = driver.findElements(By.xpath("//h3"));
System.out.println("\n--- Tüm H3 Başlıkları (XPath: //h3) ---");
if (allH3s.isEmpty()) {
System.out.println("Sayfada hiç H3 başlığı bulunamadı.");
} else {
System.out.println("Bulunan H3 başlığı sayısı: " + allH3s.size());
for (WebElement h3 : allH3s) {
System.out.println(" Başlık: " + h3.getText());
}
}
// Var olmayan bir locator ile arama (boş liste döndürür)
List nonExistentElements = driver.findElements(By.id("nonExistentClass"));
System.out.println("\n--- Var Olmayan Elementler (ID: nonExistentClass) ---");
if (nonExistentElements.isEmpty()) {
System.out.println("'nonExistentClass' ID'sine sahip element bulunamadı. (Boş liste döndü)");
} else {
System.out.println("Hata: Var olmayan elementler bulundu!");
}
} finally {
// Tarayıcıyı kapatma
driver.quit();
}
}
}
findElement() ve findElements() Arasındaki Temel Farklar
Bu iki metod arasındaki farkları anlamak, test senaryolarınızı doğru bir şekilde tasarlamanız için hayati öneme sahiptir:
| Özellik | findElement() |
findElements() |
|---|---|---|
| Amaç | Tek bir web elementi bulmak. | Belirli bir kritere uyan tüm web elementlerini bulmak. |
| Dönüş Tipi | WebElement |
List |
| Element Bulunamazsa | NoSuchElementException fırlatır. |
Boş bir List döndürür. Hata fırlatmaz. |
| Kullanım Senaryosu | Tekil bir form alanı, düğme, başlık vb. ile etkileşim kurmak. | Bir sayfadaki tüm bağlantıları, tablo satırlarını, ürün kartlarını vb. toplamak ve işlemek. |
| Performans | Genellikle daha hızlıdır çünkü ilk eşleşmeyi bulduğunda durur. | Tüm eşleşmeleri bulmak için sayfanın tamamını tarayabilir, bu nedenle daha yavaş olabilir. |
En İyi Uygulamalar ve İpuçları
Selenium ile elementleri bulurken verimliliği, sağlamlığı ve bakım kolaylığını artırmak için bazı en iyi uygulamalar mevcuttur:
1. Sağlam Locator’lar Seçin
id‘yi Tercih Edin: Mümkünse her zamanidkullanın. En hızlı ve en güvenilir locator’dır çünkü benzersiz olması beklenir.nameveclassName: Eğeridyoksa,nameveya benzersiz birclassNamedeneyin.cssSelectorKullanın:cssSelector,xpath‘e göre genellikle daha hızlı, daha okunaklı ve daha az kırılgandır. Özellikle karmaşık elementleri bulmak için güçlü bir alternatiftir.xpath‘i Dikkatli Kullanın: SadececssSelector‘ın yetersiz kaldığı durumlarda (örn. üst elemente göre arama, metin içeriğine göre arama)xpathkullanın. Göreceli XPath kullanmaya özen gösterin (//div[@id='myDiv']yerine/html/body/div[1]/div[2]gibi mutlak XPath’lerden kaçının).- Dinamik Değerlerden Kaçının: Otomatik olarak oluşturulan veya her yüklemede değişen
id‘ler veyaclass‘lardan kaçının.
2. Beklemeler (Waits) Kullanın
Modern web uygulamaları dinamiktir. Elementler sayfa yüklendikten sonra AJAX çağrıları veya JavaScript etkileşimleri ile görünebilir, kaybolabilir veya değişebilir. Elementleri bulmaya çalışmadan önce uygun beklemeleri kullanmak, NoSuchElementException hatalarını önler ve testlerinizin daha sağlam olmasını sağlar.
- Implicit Wait (Örtülü Bekleme): WebDriver’a, bir elementi bulmaya çalışırken belirli bir süre boyunca beklemesini söyler. Bir kez ayarlandığında, tüm
findElement()vefindElements()çağrıları için geçerlidir.
driver.manage().timeouts().implicitlyWait(java.time.Duration.ofSeconds(10));
import org.openqa.selenium.support.ui.WebDriverWait;
import org.openqa.selenium.support.ui.ExpectedConditions;
import java.time.Duration;
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("myElement")));
3. Hata Yönetimi
findElement()içintry-catch: Eğer bir elementin varlığı opsiyonelse veya bulunamayabileceği bir senaryo varsa,NoSuchElementException‘ı yakalamak içintry-catchblokları kullanın.findElements()içinisEmpty()Kontrolü:findElements()boş bir liste döndürdüğünde hata fırlatmadığı için, liste üzerinde işlem yapmadan öncelist.isEmpty()metodunu kullanarak listenin boş olup olmadığını kontrol edin.
4. Element Zincirleme (Chaining)
Bazen bir elementin altındaki bir elementi bulmanız gerekebilir. Bu durumda, önce ana elementi bulup, ardından bu element üzerinden findElement() veya findElements() çağırabilirsiniz. Bu, locator’larınızı daha kısa ve okunabilir hale getirebilir.
// product-list div'i içindeki tüm product-item'ları bulma
WebElement productListDiv = driver.findElement(By.className("product-list"));
List productItems = productListDiv.findElements(By.className("product-item"));
for (WebElement item : productItems) {
WebElement productTitle = item.findElement(By.tagName("h3"));
System.out.println("Ürün Başlığı: " + productTitle.getText());
}
5. Page Object Model (POM) Kullanımı
Büyük projelerde, locator’ları ve elementlerle etkileşim metotlarını ayrı sınıf dosyalarında (Page Objects) tanımlamak, kodunuzun daha düzenli, okunabilir ve bakımı kolay olmasını sağlar. Bu yaklaşım, element locator’larının tek bir yerde tanımlanmasını ve gerektiğinde kolayca güncellenmesini sağlar.
Gelişmiş Konulara Kısa Bir Bakış
findElement ve findElements metotları temel olsa da, web otomasyonunda karşılaşabileceğiniz bazı daha karmaşık senaryolar vardır:
- Iframes (Çerçeveler): Bir web sayfası içinde başka bir web sayfası barındıran
elementleri, kendi context’lerine sahiptir. Bu tür elementlerin içindeki öğeleri bulmak için önce WebDriver’ın o iframe’e geçiş yapması gerekir (driver.switchTo().frame("iframe_id_or_name")). İşiniz bittiğinde ana çerçeveye geri dönmeyi unutmayın (driver.switchTo().defaultContent()). - Shadow DOM: Bazı modern web bileşenleri Shadow DOM kullanır. Shadow DOM içindeki elementlere doğrudan standart Selenium locator’lar ile erişmek mümkün değildir. JavaScript executor veya özel Selenium eklentileri gerekebilir.
- Dinamik Tablolar ve Listeler: Sayfadaki verilerin sürekli değiştiği veya filtrelendiği durumlarda,
findElements()ve ardından liste üzerinde filtreleme/döngü işlemleri yapmak yaygın bir yaklaşımdır.
Sonuç
findElement() ve findElements() metotları, Selenium WebDriver ile web elementlerini bulmanın temel taşlarıdır. Bu metotları ve farklı locator stratejilerini ustaca kullanmak, sağlam, verimli ve bakımı kolay otomasyon betikleri yazmanın anahtarıdır. Locator’ları dikkatli seçmek, beklemeleri doğru uygulamak ve hata yönetimini göz önünde bulundurmak, otomasyon projelerinizin başarısı için kritik öneme sahiptir. Bu makalede sunulan örnekler ve en iyi uygulamalar, Selenium yolculuğunuzda size rehberlik edecektir. Pratik yaparak ve farklı web siteleri üzerinde deneyler yaparak bu becerilerinizi daha da geliştirebilirsiniz.