Playwright Test Verilerini Yönetmenin 5 Yolu | TestDino Insights
Otomasyon testleri, modern yazılım geliştirme süreçlerinin ayrılmaz bir parçasıdır. Playwright gibi güçlü bir araçla test yazarken, test verilerini etkili bir şekilde yönetmek, testlerinizin güvenilirliğini, sürdürülebilirliğini ve kapsamını doğrudan etkiler. Yanlış veya yetersiz veri yönetimi, testlerin kırılmasına, yanlış pozitiflere ve zaman kaybına yol açabilir. Bu makalede, Playwright testlerinizde veri yönetimini optimize etmek için kullanabileceğiniz beş temel yöntemi ve TestDino Insights’ın bu konudaki yaklaşımlarını detaylı bir şekilde inceleyeceğiz.
Test Verisi Yönetimi Neden Bu Kadar Önemli?
Test otomasyonunda veri yönetimi, sadece testlerin çalışmasını sağlamakla kalmaz, aynı zamanda test stratejinizin genel başarısı için kritik bir rol oynar. Doğru veri yönetimi olmadan, testleriniz hızlıca karmaşıklaşabilir ve bakımı zor hale gelebilir.
Güvenilirlik ve Tekrarlanabilirlik
Test verilerinin doğru ve tutarlı bir şekilde yönetilmesi, testlerinizin her zaman aynı koşullar altında çalışmasını sağlar. Bu da test sonuçlarının güvenilirliğini artırır ve hataların tekrarlanabilirliğini garanti eder. Aksi takdirde, aynı testin farklı zamanlarda farklı sonuçlar vermesiyle karşılaşabilirsiniz.
Test Kapsamını Genişletme
Farklı senaryoları ve uç durumları test etmek için çeşitli veri setlerine ihtiyaç duyulur. Etkili veri yönetimi, bu farklı veri setlerini kolayca oluşturmanıza ve testlerinize entegre etmenize olanak tanır, böylece test kapsamınızı genişletirsiniz.
Bakım Kolaylığı
Verilerin test kodundan ayrı tutulması, kodun daha temiz ve okunabilir olmasını sağlar. Verilerde bir değişiklik olduğunda, sadece veri kaynağını güncellemeniz yeterli olur, bu da test kodunda değişiklik yapma ihtiyacını ortadan kaldırır ve bakım maliyetlerini düşürür.
Performans ve Hız
İyi yapılandırılmış test verileri, testlerin daha hızlı çalışmasına yardımcı olabilir. Örneğin, testten önce veritabanında gerekli verileri hazırlamak veya API’ler aracılığıyla hızlıca veri oluşturmak, kullanıcı arayüzü üzerinden manuel veri girişi yapmaktan çok daha hızlıdır.
Yöntem 1: Sabit Kodlanmış (Hardcoded) ve Inline Veri Kullanımı
Test verilerini doğrudan test dosyasının içine yazmak, en basit ve en hızlı yöntemlerden biridir. Özellikle küçük, tek seferlik veya prototip testler için oldukça kullanışlıdır.
Avantajları ve Dezavantajları
Avantajları:
* Hızlı başlangıç ve kolay uygulama.
* Küçük testler veya tek kullanımlık senaryolar için ideal.
* Harici dosya veya bağımlılık gerektirmez.
Dezavantajları:
* Veri değiştiğinde test kodunun da değişmesi gerekir.
* Yeniden kullanılabilirlik düşüktür.
* Test kapsamı genişledikçe yönetimi zorlaşır.
* Hassas verilerin (şifreler gibi) kod içinde bulunması güvenlik riski oluşturabilir.
Basit Senaryolar İçin Kullanım
Bu yöntem, genellikle kullanıcı adı, şifre gibi az sayıda ve sık değişmeyen veriler için veya belirli bir form alanına girilecek tek bir değer için tercih edilir.
Playwright ile Örnek Uygulama
Aşağıdaki örnekte, bir giriş testi için kullanıcı adı ve şifrenin doğrudan test içinde nasıl kullanıldığını görebilirsiniz:
import { test, expect } from '@playwright/test';
test('Kullanıcı geçerli kimlik bilgileriyle giriş yapabilmeli', async ({ page }) => {
const username = 'testuser';
const password = 'password123';
await page.goto('https://example.com/login');
await page.fill('#username', username);
await page.fill('#password', password);
await page.click('#loginButton');
await expect(page.url()).toContain('/dashboard');
await expect(page.locator('.welcome-message')).toHaveText(Hoş geldiniz, ${username}!);
});
Yöntem 2: Yapılandırma Dosyaları ile Veri Yönetimi (JSON, YAML, .env)
Test verilerini harici yapılandırma dosyalarında saklamak, daha büyük ve karmaşık projeler için sabit kodlanmış verilere göre çok daha iyi bir yaklaşımdır. Bu yöntem, verileri koddan ayırarak daha temiz, daha yönetilebilir ve daha güvenli testler oluşturmanıza yardımcı olur.
JSON Dosyaları ile Yapılandırılmış Veri
JSON (JavaScript Object Notation), yapılandırılmış verileri depolamak için yaygın olarak kullanılan hafif bir veri değişim formatıdır. Kullanıcı profilleri, ürün detayları veya test senaryoları gibi karmaşık veri yapılarını saklamak için idealdir.
Örnek test-data.json:
{
"users": [
{
"username": "adminUser",
"password": "adminPassword",
"role": "admin"
},
{
"username": "standardUser",
"password": "userPassword",
"role": "user"
}
],
"products": [
{
"name": "Laptop",
"price": 1200,
"quantity": 1
},
{
"name": "Mouse",
"price": 25,
"quantity": 2
}
]
}
Ortam Değişkenleri ve .env Kullanımı
Ortam değişkenleri, özellikle hassas veriler (API anahtarları, veritabanı bağlantı dizeleri) ve ortamdan ortama değişen veriler (test ortamı URL'leri) için mükemmel bir çözümdür. dotenv paketi, .env dosyalarından ortam değişkenlerini yüklemeyi kolaylaştırır.
Örnek .env dosyası:
BASE_URL=https://test.example.com
API_KEY=your_secret_api_key
ADMIN_USERNAME=adminUser
ADMIN_PASSWORD=adminPassword
Playwright Testlerinde Entegrasyon
JSON verilerini okumak için Node.js'in fs modülünü kullanabilir, ortam değişkenlerine ise process.env üzerinden erişebilirsiniz.
import { test, expect } from '@playwright/test';
import * as fs from 'fs';
import * as path from 'path';
import dotenv from 'dotenv';
// .env dosyasını yükle
dotenv.config();
// JSON verisini oku
const testDataPath = path.join(__dirname, 'test-data.json');
const testData = JSON.parse(fs.readFileSync(testDataPath, 'utf-8'));
test('Admin kullanıcısı giriş yapabilmeli', async ({ page }) => {
const adminUser = testData.users.find(user => user.role === 'admin');
const baseUrl = process.env.BASE_URL || 'https://default.example.com';
await page.goto(${baseUrl}/login);
await page.fill('#username', adminUser.username);
await page.fill('#password', adminUser.password);
await page.click('#loginButton');
await expect(page.url()).toContain('/admin-dashboard');
});
test('Ürün sepete eklenebilmeli', async ({ page }) => {
const product = testData.products[0]; // Laptop
await page.goto(process.env.BASE_URL || 'https://default.example.com');
await page.locator(text=${product.name}).click();
await page.click('#addToCartButton');
await expect(page.locator('.cart-item-count')).toHaveText('1');
});
Yöntem 3: Dinamik Veri Üreticileri (Faker.js vb.)
Bazen, özellikle kayıt formları veya veri girişi testleri gibi senaryolarda, her test çalıştırmasında benzersiz ve gerçekçi verilere ihtiyacınız olur. Dinamik veri üreticileri, bu ihtiyacı karşılamak için mükemmel araçlardır.
Neden Dinamik Veriye İhtiyaç Duyarız?
* Benzersizlik: Kullanıcı adı veya e-posta gibi alanların her testte benzersiz olması gerekebilir, aksi takdirde çakışmalar yaşanabilir.
* Gerçekçilik: Rastgele ancak gerçekçi isimler, adresler, telefon numaraları, testlerin daha gerçekçi senaryoları simüle etmesine yardımcı olur.
* Test Kapsamı: Farklı veri türleri ve formatları ile uygulamayı test etmek, daha geniş bir hata yelpazesini ortaya çıkarabilir.
* Veri Kirliliği: Test ortamında sürekli aynı verileri kullanmak yerine, dinamik veriler sayesinde veri kirliliğini azaltabilirsiniz.
Faker.js ile Gerçekçi Veri Üretimi
faker-js (eski adıyla faker.js), Node.js ortamında sahte ancak gerçekçi veri üretmek için en popüler kütüphanelerden biridir. İsimler, adresler, e-postalar, telefon numaraları, ürünler ve daha fazlasını kolayca üretebilir.
Kurulum:
npm install @faker-js/faker
Playwright Testlerinde Kullanım Örnekleri
import { test, expect } from '@playwright/test';
import { faker } from '@faker-js/faker';
test('Yeni kullanıcı kaydı başarılı olmalı', async ({ page }) => {
const firstName = faker.person.firstName();
const lastName = faker.person.lastName();
const email = faker.internet.email({ firstName, lastName });
const password = faker.internet.password({ length: 10, memorable: true, pattern: /[A-Z0-9]/ });
await page.goto('https://example.com/register');
await page.fill('#firstName', firstName);
await page.fill('#lastName', lastName);
await page.fill('#email', email);
await page.fill('#password', password);
await page.fill('#confirmPassword', password);
await page.click('#registerButton');
await expect(page.url()).toContain('/registration-success');
await expect(page.locator('.success-message')).toHaveText('Kaydınız başarıyla tamamlandı!');
});
test('Ürün yorumu eklenebilmeli', async ({ page }) => {
const reviewText = faker.lorem.paragraph();
const rating = faker.number.int({ min: 1, max: 5 });
await page.goto('https://example.com/product/123'); // Belirli bir ürün sayfasına git
await page.click('#addReviewButton');
await page.fill('#reviewText', reviewText);
await page.locator(input[name="rating"][value="${rating}"]).check();
await page.click('#submitReview');
await expect(page.locator('.review-list')).toContainText(reviewText);
});
Yöntem 4: Veritabanı ve API Entegrasyonları
Karmaşık senaryolarda veya uygulamanın belirli bir durumunu test etmek için, doğrudan veritabanı veya API'ler aracılığıyla test verisi hazırlamak veya sorgulamak çok daha verimli olabilir. Bu yöntem, UI testlerinden önce sistemin arka ucunda gerekli veriyi oluşturmanıza olanak tanır.
Gerçek Dünya Senaryoları İçin Veritabanı Yönetimi
Veritabanı entegrasyonu, özellikle aşağıdaki durumlarda faydalıdır:
* Ön Koşul Verisi: Bir testin başlaması için belirli bir kullanıcı durumu, ürün envanteri veya sipariş geçmişi gibi verilerin önceden var olması gerektiğinde.
* Veri Temizliği: Her test çalıştırmasından sonra veritabanını temizleyerek testler arası bağımlılıkları ortadan kaldırmak.
* Doğrulama: UI üzerinde yapılan bir işlemin veritabanında doğru bir şekilde yansıtılıp yansıtılmadığını kontrol etmek.
Node.js'te popüler veritabanı sürücüleri arasında mysql2, pg (PostgreSQL için) ve mongoose (MongoDB için) bulunur.
API'ler Aracılığıyla Test Verisi Oluşturma
Uygulamanızın bir API'si varsa, bu API'yi kullanarak test verisi oluşturmak veya değiştirmek, UI üzerinden manuel olarak işlem yapmaktan çok daha hızlı ve güvenilirdir. Bu, özellikle bir kayıt, ürün ekleme veya sipariş oluşturma gibi işlemler için geçerlidir. axios veya yerleşik fetch API'si, HTTP istekleri yapmak için kullanılabilir.
Playwright Testlerinde Veri Hazırlığı
Playwright testlerinde, test.beforeAll veya test.beforeEach kancalarını kullanarak testlerden önce veritabanı veya API işlemlerini gerçekleştirebilirsiniz.
import { test, expect } from '@playwright/test';
import axios from 'axios';
import { Client } from 'pg'; // PostgreSQL örneği
// Veritabanı bağlantı bilgileri (örneğin .env dosyasından okunabilir)
const dbConfig = {
user: 'testuser',
host: 'localhost',
database: 'testdb',
password: 'testpassword',
port: 5432,
};
let pgClient: Client;
let createdUserId: number;
test.beforeAll(async () => {
// Veritabanı bağlantısını kur
pgClient = new Client(dbConfig);
await pgClient.connect();
// Testten önce veritabanını temizle
await pgClient.query('DELETE FROM users WHERE email LIKE \'testuser_%\'');
// API aracılığıyla yeni bir kullanıcı oluştur
const newUserResponse = await axios.post('http://localhost:3000/api/users', {
username: 'testuser_' + Date.now(),
email: 'testuser_' + Date.now() + '@example.com',
password: 'password123'
});
createdUserId = newUserResponse.data.id;
console.log(API ile kullanıcı oluşturuldu: ID ${createdUserId});
});
test.afterAll(async () => {
// Testlerden sonra oluşturulan kullanıcıyı veritabanından sil
if (createdUserId) {
await pgClient.query('DELETE FROM users WHERE id = $1', [createdUserId]);
console.log(Kullanıcı silindi: ID ${createdUserId});
}
await pgClient.end();
});
test('API ile oluşturulan kullanıcı giriş yapabilmeli', async ({ page }) => {
// Veritabanından oluşturulan kullanıcının bilgilerini al
const result = await pgClient.query('SELECT * FROM users WHERE id = $1', [createdUserId]);
const user = result.rows[0];
await page.goto('http://localhost:3000/login');
await page.fill('#email', user.email);
await page.fill('#password', 'password123'); // API ile oluşturulurken verilen şifre
await page.click('#loginButton');
await expect(page.url()).toContain('/dashboard');
await expect(page.locator('.welcome-message')).toHaveText(Hoş geldiniz, ${user.username}!);
});
Yöntem 5: Test Verilerini Playwright Test Yapısına Entegre Etme (Fixtures, POM)
Playwright'ın güçlü test yapısı, test verilerini daha düzenli ve yeniden kullanılabilir bir şekilde yönetmek için özel araçlar sunar. Fixture'lar ve Page Object Model (POM), bu entegrasyonu sağlamanın ana yollarıdır.
Playwright Fixture'ları ile Veri Paylaşımı
Playwright'ın test.extend özelliği, testler arasında paylaşılan kaynakları (fixtures) tanımlamanıza olanak tanır. Bu kaynaklar, test verileri, önceden yapılandırılmış sayfalar veya özel yardımcı fonksiyonlar olabilir. Fixture'lar, test verilerini test kodundan ayırarak daha temiz ve modüler testler yazmanızı sağlar.
Örnek Fixture Tanımlama:
tests/fixtures/auth.ts
import { test as baseTest } from '@playwright/test';
type MyFixtures = {
loggedInUser: { username: string; email: string; };
loginAsUser: (username: string, password: string) => Promise;
};
export const test = baseTest.extend({
loggedInUser: async ({ page }, use) => {
// Gerçek bir kullanıcı girişi simüle et
const username = 'fixtureUser';
const email = 'fixture@example.com';
const password = 'fixturePassword';
await page.goto('https://example.com/login');
await page.fill('#username', username);
await page.fill('#password', password);
await page.click('#loginButton');
await page.waitForURL('**/dashboard');
await use({ username, email }); // Teste bu kullanıcı verilerini sağla
},
loginAsUser: async ({ page }, use) => {
// Giriş fonksiyonunu fixture olarak sun
await use(async (username, password) => {
await page.goto('https://example.com/login');
await page.fill('#username', username);
await page.fill('#password', password);
await page.click('#loginButton');
await page.waitForURL('**/dashboard');
});
},
});
Fixture Kullanımı:
import { test, expect } from '../fixtures/auth'; // Özel fixture'ımızı import et
test('Oturum açmış kullanıcı paneli görebilmeli', async ({ page, loggedInUser }) => {
await expect(page.locator('.welcome-message')).toHaveText(Hoş geldiniz, ${loggedInUser.username}!);
});
test('Farklı bir kullanıcı olarak giriş yapabilmeli', async ({ page, loginAsUser }) => {
await loginAsUser('anotherUser', 'anotherPassword');
await expect(page.locator('.welcome-message')).toHaveText('Hoş geldiniz, anotherUser!');
});
Page Object Model ve Veri Enkapsülasyonu
Page Object Model (POM), web sayfalarını nesneler olarak temsil eden bir tasarım desenidir. Her sayfa nesnesi, o sayfadaki elemanları (locator'ları) ve bu elemanlarla etkileşim kuran yöntemleri içerir. Test verilerini, sayfa nesneleri içinde veya onlara parametre olarak geçirerek enkapsüle edebilirsiniz. Bu, testlerin daha okunabilir, sürdürülebilir ve yeniden kullanılabilir olmasını sağlar.
Örnek Page Object:
pages/LoginPage.ts
import { Page, Locator } from '@playwright/test';
export class LoginPage {
readonly page: Page;
readonly usernameInput: Locator;
readonly passwordInput: Locator;
readonly loginButton: Locator;
readonly errorMessage: Locator;
constructor(page: Page) {
this.page = page;
this.usernameInput = page.locator('#username');
this.passwordInput = page.locator('#password');
this.loginButton = page.locator('#loginButton');
this.errorMessage = page.locator('.error-message');
}
async navigate() {
await this.page.goto('https://example.com/login');
}
async login(username: string, password: string) {
await this.usernameInput.fill(username);
await this.passwordInput.fill(password);
await this.loginButton.click();
}
}
POM ile Test Verisi Kullanımı:
import { test, expect } from '@playwright/test';
import { LoginPage } from '../pages/LoginPage';
test('Geçersiz kimlik bilgileriyle giriş yapılamamalı', async ({ page }) => {
const loginPage = new LoginPage(page);
await loginPage.navigate();
// Test verisi doğrudan test içinde veya harici bir kaynaktan gelebilir
const invalidUsername = 'invaliduser';
const invalidPassword = 'wrongpassword';
await loginPage.login(invalidUsername, invalidPassword);
await expect(loginPage.errorMessage).toBeVisible();
await expect(loginPage.errorMessage).toHaveText('Geçersiz kullanıcı adı veya şifre.');
});
Modüler ve Yeniden Kullanılabilir Testler
Fixtures ve POM'u bir arada kullanarak, test verilerinizi ve etkileşimlerinizi modüler bir yapıda tutabilirsiniz. Bu, aynı test verilerini veya veri hazırlık adımlarını farklı testlerde kolayca yeniden kullanmanızı sağlar, böylece kod tekrarını azaltır ve testlerin bakımını basitleştirir.
En İyi Uygulamalar ve İpuçları
Test verisi yönetimi stratejinizi oluştururken göz önünde bulundurmanız gereken bazı önemli noktalar şunlardır:
Veri Bağımsızlığını Sağlama
Her testin kendi verisi üzerinde çalışmasını sağlayın ve testler arasında veri bağımlılıklarını minimize edin. Bir testin diğerini etkilememesi için, testlerden önce veritabanı temizliği veya dinamik veri üretimi gibi yöntemleri kullanın.
Veri Temizliği ve Geri Alma
Testlerden sonra oluşturulan verileri temizlemek (örneğin, veritabanından silmek veya API aracılığıyla silme işlemi yapmak) çok önemlidir. Bu, test ortamının bir sonraki çalıştırma için temiz kalmasını sağlar ve testler arası çakışmaları önler. test.afterEach veya test.afterAll kancaları bu amaçla kullanılabilir.
Güvenlik ve Hassas Veriler
Şifreler, API anahtarları veya kişisel bilgiler gibi hassas verileri asla doğrudan kod içine veya versiyon kontrol sistemine (Git gibi) yüklenen dosyalara yazmayın. Bunun yerine, .env dosyaları, ortam değişkenleri veya güvenli bir sır yönetimi çözümü kullanın.
Ölçeklenebilirlik İçin Stratejiler
Projeniz büyüdükçe ve test sayınız arttıkça, veri yönetim stratejinizin ölçeklenebilir olması gerekir.
* Veri Havuzları: Büyük veri setlerini yönetmek için merkezi bir veri havuzu veya test verisi yönetim sistemi kullanmayı düşünebilirsiniz.
* Parametrelendirilmiş Testler: Playwright'ın test.describe.configure({ mode: 'parallel' }) ve döngülerle testleri parametreleştirerek farklı veri setleriyle aynı testi birden çok kez çalıştırın.
* Test Verisi Oluşturma Araçları: Kapsamlı test verisi oluşturmak için özel araçlar veya komut dosyaları geliştirin.
Sonuç
Playwright ile etkili otomasyon testleri yazmak, sağlam bir test verisi yönetim stratejisi gerektirir. Sabit kodlanmış verilerden dinamik üreticilere, yapılandırma dosyalarından veritabanı ve API entegrasyonlarına kadar birçok farklı yöntem bulunmaktadır. Playwright'ın fixture'ları ve Page Object Model gibi yerleşik özellikleriyle bu yöntemleri birleştirerek, testlerinizin güvenilirliğini, sürdürülebilirliğini ve genel kalitesini önemli ölçüde artırabilirsiniz. TestDino Insights olarak, test otomasyon süreçlerinizde en uygun veri yönetim yaklaşımlarını benimsemenizi ve böylece daha sağlam, hızlı ve bakımı kolay test paketleri oluşturmanızı öneriyoruz.
SSS (Sık Sorulan Sorular)
1. Hangi test verisi yönetim yöntemi benim projem için en iyisidir?
Projenizin büyüklüğüne, karmaşıklığına, test senaryolarınızın doğasına ve hassas veri gereksinimlerinize bağlıdır. Küçük projeler için sabit kodlanmış veriler veya JSON dosyaları yeterli olabilirken, büyük ve karmaşık projeler için dinamik veri üreticileri, veritabanı/API entegrasyonları ve Playwright fixture'ları gibi daha gelişmiş yöntemlerin bir kombinasyonu gerekebilir.
2. Test verilerini harici bir dosyada saklamak ne gibi avantajlar sağlar?
Harici dosyalarda (JSON, YAML, .env) veri saklamak, verileri test kodundan ayırır. Bu, kodun daha temiz ve okunabilir olmasını sağlar, verilerde değişiklik olduğunda sadece veri dosyasını güncelleme esnekliği sunar ve hassas verileri versiyon kontrolünden ayrı tutarak güvenliği artırır.
3. Playwright fixture'ları test verisi yönetiminde nasıl yardımcı olur?
Playwright fixture'ları, testler arasında paylaşılan kaynakları (örneğin, önceden oluşturulmuş kullanıcı oturumları, belirli veri setleri) tanımlamanıza olanak tanır. Bu, veri hazırlık adımlarını merkezileştirir, kod tekrarını azaltır ve testlerin daha modüler ve okunabilir olmasını sağlar.
4. Dinamik veri üreticileri (Faker.js gibi) ne zaman kullanılmalıdır?
Dinamik veri üreticileri, her test çalıştırmasında benzersiz ve gerçekçi verilere ihtiyaç duyduğunuzda kullanılmalıdır. Özellikle yeni kullanıcı kaydı, form doldurma, ürün yorumu ekleme gibi senaryolarda veri çakışmalarını önlemek ve test kapsamını genişletmek için idealdir.
5. Testlerden sonra test verilerini temizlemek neden önemlidir?
Testlerden sonra oluşturulan verileri temizlemek, test ortamının bir sonraki çalıştırma için temiz ve öngörülebilir kalmasını sağlar. Bu, testler arası bağımlılıkları ve çakışmaları önler, böylece test sonuçlarının güvenilirliğini artırır ve "flaky" (aralıklı olarak başarısız olan) testlerin oluşmasını engeller.
