Test Otomasyon Projesinde Extension Metotların Kullanımı

Test otomasyon projelerinde sıklıkla primitive ve generic veri tipleriyle haşır neşir oluruz.

Aynı zamanda ilgili veri tiplerini manipüle etmeye çalışırız.

Extension metotlar:

  • Verileri manipüle etmenin,

  • Var olan sınıflara, source kod’a müdehale etmeden, yeni bir işlevsellik kazandırmanın,

  • Temiz ve sürdürülebilir kod yazmanın iyi bir yoludur.

Yanılmıyorsam, Paracelsus şöyle demiş:

Her şey zehirdir, mühim olan dozdur.

Bu minvalde düşünüldüğünde okunabilir ve temiz kod yazalım diye çıktığımız yolda her şeyi extension metotlarla yazmak bir süre sonra projeyi okunabilir ve temiz olmaktan çıkarabilir. O halde neleri extension metotla yazacağınızı oturup ekibinizle konuşmak dozu kaçırmanıza mani olabilir. Türkçe’ye “genişletilmiş yöntemler“ olarak çevirebildiğim extension method'ların avantaj ve dezavantajlarına birlikte göz atalım.

Avantajlar:

  • Okunabilirlik: Kod, daha temiz ve daha doğal görünür. Metot, ilgili sınıfın doğal bir parçasıymış gibi davranır.

  • Modülerlik: Extension metotları, kodun daha modüler ve sürdürülebilir olmasını sağlar.

  • Tekrar Kullanılabilirlik: Mevcut sınıflara yeni işlevler ekleyerek kodun yeniden kullanılabilirliğini artırır. Extension metotlar, benzer işlevselliği tekrar tekrar yazma ihtiyacını ortadan kaldırır. Bu, koda bakım yapmayı ve güncellemeyi kolaylaştırır.

  • Tesadüfen Denk Gelmek 😀: Hadi kabul edelim, hepimiz en az bir kere IDE’ye değişken ismini yazdıktan sonra “.“ tuşuna basıp, ilgili değişkenden sonra hangi metotları kullanabiliyorum acaba diye bakmışızdır. Extension metotlar, tam da değişken isminden sonra “.“ tuşuna basıldığında ekrana gelen listede görüldüğü için kullanıcılar tarafından sezgisel olarak keşfedebilir.

Dezavantajlar:

  • Çakışma Riski: Eğer extension metotları, mevcut metodlarla aynı isimde tanımlarsanız, çakışmalar meydana gelebilir. Kendinizi abuk subuk hatalarla veya tutarsızlıklarla cebelleşiyorken bulabilirsiniz.

    • Örnek: Diyelim ki X adında String extension metot geliştirdiniz. Eğer bağımlılık olarak eklediğiniz başka bir kütüphane de String.prototype.X metodunu extend ederse ve sizin implementasyonunuz farklıysa, bu durumda yanlış sonuçlar/tutarsızlıklar olabilir.
  • Performans Sorunları: “Çok sayıda extension metodu tanımlamak, performans üzerinde olumsuz etkiler yaratabilir” diyorlar. Bu konuda deneyimim yok. Fakat şahsi düşüncem söylenenler doğru olsa bile test otomasyon projesinde performans problemi oluşacağını düşünmüyorum. Düşük bi’ ihtimalle de olsa, ürün kodu yazılan projelerde böyle bir problem olabilir.

İlk Extension Metodumuzu Yazalım ve Satır Satır İnceleyelim

Extension’u yazmaya başlamadan önce şunlara sahip olduğunuzdan emin olunuz:

Malzemeler:

  • İlgili bilgisayarda Node.js’ın yüklü olması

  • TS çalıştırabilecek bir proje oluşturmuş olmanız veya ilgili bilgisayarda Playwright projesi oluşturmuş olmak. Ben PW projesi oluşturdum ve oradan devam edeceğim, dilerseniz siz de şuradaki kurulum adımlarını takip edebilirsiniz:

isNumeric Extension Metodunun Yazılması

Amaç: isNumeric extension metodu ile, elimizdeki string içinde sadece rakamlar mı var yoksa farklı karakterler de içeriyor mu? Onu kontrol edip true veya false döndürüyoruz.

// dosya adı: string-extension.ts

// String arayüzüne `isNumeric` adında yeni bir metot eklemek için tanımlama yapıyoruz.
interface String {
    isNumeric(): boolean;
}

// Akabinde `isNumeric` metodunun implementasyonuna başlıyoruz
String.prototype.isNumeric = function (): boolean {
    // Burada sadece rakamlardan oluşan string ile eşleşen regex tanımı yapıyoruz.
    const numericRegex = /^-?\d+$/;

    // test metodu ile string'in düzenli ifadeye uyup uymadığı kontrol edilir.
    // "this" string'in kendisini ifade eder. 
    return numericRegex.test(this); 
};

isNumeric extension metodunun kullanımı:

// dosya adı: example.spec.ts

// string extensionları yazdığımız dosyayı import etmemiz gerekmekte, aksi durumda şu hata alınır:
// TypeError: onlyNumbers.isNumeric() is not a function
import '../tests/string-extension';

test('isNumeric extension method example', async () => {
  const onlyNumbers = "0123456789";
  const mixedLettersAndNumbers = "zaf3r";
  const negativeNumbers = "-123";

  console.log(onlyNumbers.isNumeric()); // Çıktı: true 
  console.log(mixedLettersAndNumbers.isNumeric()); // Çıktı: false
  console.log(negativeNumbers.isNumeric()); // Çıktı: true
});

Örnek Extension Metotları Çoğaltalım

isValidEmail Extension Metodunun Yazılması

Amaç: String içindeki değer gerçekten email mi, değil mi bunu anlayabilmek.

// dosya adı: string-extension.ts
interface String {
    isValidEmail(): boolean;
}

String.prototype.isValidEmail = function (): boolean {
    const emailRegex = /^[\w-\.]+@[\w-]+\.[a-z]{2,}$/i;
    return emailRegex.test(this);
};

isValidEmail extension metodunun kullanımı:

// dosya adı: example.spec.ts
import '../tests/string-extension';

test('isValidEmail extension method example', async () => {
  const email = "test@example.com";
  console.log(email.isValidEmail()); // Çıktı: true

  const invalidEmail = "not-an-email";
  console.log(invalidEmail.isValidEmail()); // Çıktı: false
});

extractNumbers Extension Metodunun Yazılması

Amaç: Bir string içerisinde yer alan rakamları, diğer karakterlerden arındırmak.

interface String {
    extractNumbers(): string;
}

String.prototype.extractNumbers = function (): string {
    const digitRegex = /\d+/g; // String içindeki tüm rakamları eşleyen regex.
    const matches = this.match(digitRegex); // String içindeki eşleşen rakamları dizi olarak döndürür.
    return matches ? matches.join("") : ""; // Eğer eşleşme varsa birleştir, yoksa boş string döndür.
};

extractNumber extension metodu kullanımı:

// dosya adı: example.spec.ts
import '../tests/string-extension';

test('exractNumbers extension method example', async () => {
  const example1 = "z1a2f3e4r5";
  console.log(example1.extractNumbers()); // Çıktı: 12345
});

Toparlayalım

Test otomasyon projelerinde gerek API’den dönen cevap, gerekse DOM üzerinden okuduğumuz veri kirli olabilir. Bu kirli verileri temizlemek için projenizde extension metotları kullanmak sizlere okunabilir, temiz kod yazımında katkı sağlayabilir. Örnekleri hep String veri tipi üzerinden verdiğimi fark etmişsinizdir, extension metotlar sadece Stringveri tipleriyle sınırlı değildir. Aşağıdaki veri tipleri için de extension metot yazabilirsiniz:

Built-in JS Türleri: String, Number, Array, Date, Function

User-Defined Types: Kullanıcı tanımlı interface ve class yapıları da genişletilebilir.

Primitive Türler:boolean, null, undefined

Not: Extension metotlar C# ve TypeScript dillerinde desteklenirken Java dilinde desteklenmezler. Bu minik problem genellikle StringUtils sınıflarıyla telafi edilir.

Vakit ayırdığın için teşekkürler, sonraki yazıda tekrar görüşelim 👋 👋