Selenium Best Practices
Selenium WebDriver, uzun yıllardır UI test otomasyonunun amiral gemilerinden biri. Fakat Selenium’un güçlü olmasını sağlayan şey, sadece WebDriver komutları değil; nasıl bir mimari kurduğunuz, locator stratejileriniz, bekleme yapılarını nasıl yönettiğiniz ve testleri nasıl organize ettiğinizdir. Bu yazıda, pratikte işe yarayan ve test senaryolarını gerçekten stabil hâle getiren en iyi uygulamaları adım adım inceleyelim.
1. Doğru Mimariyi Kurun
POM, test otomasyon projelerinde sürdürülebilirliği en çok artıran yaklaşımdır. Çünkü test senaryolarının içinde element locator’ları tutmak uzun vadede kabusa dönüşür. Sayfa değişikliklerinde yüzlerce test kırılır ve bakım maliyeti katlanır. POM sayesinde her sayfa için tek bir sınıf oluşturursun; elementleri bu sınıfta toplar, testleri ise sadece bu sınıfın metodlarını çağırarak yazarsın. Böylece test kodu daha okunaklı, daha az kırılan ve daha kolay genişletilebilir olur.
POM kullanmak:
- Kod tekrarını azaltır
- Bakımı kolaylaştırır
- Gösterimli ve temiz bir mimari sağlar
İpuçları:
- Reusable metotlar oluşturun (login(), search(), logout() gibi)
- Her sayfa için ayrı bir sınıf oluşturun
- Element bulma işlemlerini testlerden tamamen ayırın
Örnek POM Kullanımı için aşağıdaki örneği inceleyelim.
public class LoginPage {
private WebDriver driver;
@FindBy(id = "username")
private WebElement username;
@FindBy(id = "password")
private WebElement password;
@FindBy(css = "button[type='submit']")
private WebElement loginButton;
public LoginPage(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver, this);
}
public void login(String user, String pass) {
username.sendKeys(user);
password.sendKeys(pass);
loginButton.click();
}
}Test sınıflarımızda sadece ilgili metotları çağırarak kullanmak kalıyor, tamamen locator bağı kalmamış oluyor. Bu da temiz mimarinin en büyük adımıdır.
2. Doğru Bekleme Stratejileri Kullanın
Modern web uygulamaları dinamik. Elementler DOM’a hemen gelmeyebiliyor veya AJAX çağrıları araya giriyor. Bu nedenle doğru bekleme yapısı kurmazsan testler belirsiz hatalar üretmeye başlar. Thread.sleep() gibi sabit beklemeler her zaman kötü pratik olarak kabul edilir çünkü:
- Testleri gereksiz yavaşlatır
- Stabil değildir
- Dinamik sayfalarla çalışmaz
Bunun yerine explicit wait veya fluent wait kullanmak çok daha sağlıklıdır.
Explicit Wait kullanımı için aşağıdaki örneği inceleyelim.
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
WebElement element = wait.until(
ExpectedConditions.visibilityOfElementLocated(By.id("result"))
);
Bu yöntem sayfa ne kadar hızlı yüklenirse o kadar hızlı devam eder; yavaş kalırsa bekler.
3. Doğru Locator Seçimleri
Doğru locator seçimi, test stabilitesini doğrudan etkiler. Çoğu yeni başlayan test uzmanının yaptığı en büyük hata her element için XPath yazmak ama XPath karmaşıklaştıkça kırılma riski artar. Performans açısından CSS Selector çoğu zaman XPath’ten hızlıdır.
Önerilen sıraya göre locator kullanımı:
- id
- name
- cssSelector
- xpath
Bu durumu iki örnek kodla inceleyelim, aşağıda kırılgan kötü yazılmış bir Xpath örneği yer alıyor.
driver.findElement(By.xpath("/html/body/div[1]/div/div[2]/ul/li[3]/a"));
Yukarıdaki kötü yazılmış Xpath örneğinin tersine iyi tasarlanmış kısa ve performanslı çalışacak olan cssSelector locator örneği yer alıyor.
driver.findElement(By.cssSelector("ul.menu li:nth-child(3) a"));4. Tekrarlanan Kodları Ortadan Kaldırın
Gerçek projelerde aynı kodları defalarca yazmak zorunda kalabilirsiniz, scroll, element görünene kadar bekleme, ekran görüntüsü alma, random data üretme gibi temelde hep aynı işlemleri yapan utility metotlar. Bunların hepsini utility sınıflarına toplamak hem kodu sadeleştirir hem de tekrar kullanılabilir hâle getirir.
Aşağıdaki örnek utility metot sayesinde her seferinde ilgili elementlere bekleme satırları da eklemekten kurtulmuş oluyoruz bu sayede kod tekrarını engelleyip bakımı kolay otomasyon kodları yazabiliyoruz.
public class WaitUtils {
public static WebElement waitForVisible(WebDriver driver, By locator, int seconds) {
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(seconds));
return wait.until(ExpectedConditions.visibilityOfElementLocated(locator));
}
}Yazdığımz metoduda aşağıdaki gibi basitçe çağırıp kullanabiliyoruz.
WaitUtils.waitForVisible(driver, By.id("title"), 10);5. Cross-Browser Testlerini Otomatikleştirin
Selenium WebDriver’in en büyük avantajlarından biri de çoklu tarayıcı desteği. Tek tarayıcıda çalışan test seti, gerçek dünyada hiçbir zaman yeterli olmaz. Kullanıcıların Chrome, Edge, Safari, Firefox gibi tarayıcıları var.
En iyi uygulamalar:
- Docker + Selenium Grid kullanarak paralel test çalıştırın
- Testleri Chrome, Firefox, Edge gibi farklı tarayıcılarda koşun
- Tarayıcı seçimini config dosyasından alın
String browser = System.getProperty("browser", "chrome");6. Test Verilerini Kod İçinde Tutmayın
Hard-coded test datası hem güvenlik açısından hem de bakım açısından sakıncalıdır. Parola, kullanıcı adı, test edilecek sayfaya ait url bilgisi gibi değerleri config dosyalarına taşımak daha temiz bir yaklaşımdır. Yine 4 numaralı konu başlığında anlattığımız gibi test verilerini okumamızı sağlayan utility metotlar yazarak, en iyi uygulama örneklerini projelerinizde uygulamış olursunuz.
Doğru yöntem:
- JSON
- CSV
- Excel
- Environment variables
- YAML gibi harici dosyalardan test verilerini çekerek testlerinizi koşabilirsiniz, bu sayede test verisine olan bağımlığınız kod düzeyinde ortadan kalkmış olur ve bu süreci kolay yönetebilirsiniz.
7. Loglama ve Raporlama Kullanın
UI testleri doğası gereği kırılmaya açıktır bu nedenle bir hata olduğunda neden kırıldığını görebilmek kritik öneme sahiptir. Ayrıca başarısız testlerin ekran görüntülerini almayı da standart hale getirmelisiniz. Raporlar sayesinde hataların kök nedenini bulmak kolaylaşır.
Önerilen araçlar:
- Extent Reports
- Allure Report
- Jenkins + HTML publisher
8. Testleri Bağımsız ve İzole Yazın
Bir testin başarısı diğerine bağlıysa o test seti sağlıklı değildir. Örneğin önce login olan bir test, sonra başka bir testin login olmuş aynı state’i kullanması doğru değildir. Bu yaklaşım uzun vadede en büyük kazancı sağlar.
Bağımsız testler;
- Birbirine bağımlı değildir
- Sıra değiştiğinde bozulmaz
- Ortak state kullanmaz
Ayrıca bu yaklaşım, 5 numaralı madde de bahsettiğim paralel test çalıştırmayı da mümkün kılacaktır.
9. Sürüm Kontrol Entegrasyonu Kullanın
Test otomasyonu da yazılım geliştirme disipliniyle ilerlemelidir; aksi hâlde kod kalitesi hızla bozulur. Ana branchten (örneğin master) yeni bir geliştirme branch’i açılmalıdır. Burada istenilen geliştirme gerçekleştirildikten sonra pull request mantığıyla, yazılan kodlar daha tecrübeli test uzmanları tarafından incelenmelidir. İnceleme sonrasında kod ana branch’e merge edilmeli ve otomatik olarak varsa CI/CD pipeline tetiklenmelidir.
Tüm test kodlarınız:
- Git
- SVN
- GitHub / GitLab / Azure DevOps reposu
gibi sürüm kontrol sistemlerinde tutulmalıdır.
En iyi uygulama:
Feature branch → PR → Code review → Merge → Pipeline → Otomatik Test Koşumu
10. CI/CD ile Testleri Otomatik Çalıştırın
Selenium testleri sadece lokal ortamda değil, sürekli entegrasyon süreçlerinde de çalıştırılmalıdır.
Önerilen platformlar:
- Azure DevOps
- Jenkins
- GitHub Actions
- GitLab CI/CD
Testlerin:
- Pull Request açıldığında,
- Her push işleminde,
- Her release öncesi,
- Her nightly build’de otomatik çalıştırılması gerekir.
Bu otomasyon hem kaliteyi artırır hem de manuel test yükünü azaltır.
Sonuç
Selenium ile stabil, hızlı ve bakımı kolay bir test mimarisi oluşturmanın yolu, doğru mimari kararlarından ve disiplinli bir yaklaşımdan geçiyor. Bu yazımdaki pratiklerin çoğu, gerçek projelerde karşılaşılan sorunlardan edinilmiş tecrübelerimin bir özetidir. Test otomasyonunu bir yazılım projesi gibi ele aldığında Selenium hem güçlü hem de esnek bir araç hâline gelir. Bu yazımda Selenium WebDriver’da test uzmanlarının uygulaması gereken temel best practice’leri anlattım. Test otomasyon projelerinizde bu prensipleri takip ettiğinizde:
- Daha stabil
- Daha hızlı
- Daha kolay bakım yapılan
- Daha ölçeklenebilir bir test mimarisine sahip olabilirsiniz.