Durumumuzu açıkça ifade edelim: Biz Geonode olarak proxy satışı yapıyoruz ve Playwright, veri toplama ve coğrafi testler için sıklıkla bu proxy’ler üzerinden çalıştırılıyor. Dürüstçe belirtmek gerekirse, Playwright zaman aşımlarının ezici çoğunluğunun proxy'lerle hiçbir ilgisi yoktur. Hiçbir şeyle eşleşmeyen bir seçici, çerez uyarısı ile örtülmüş bir öğe, hiçbir zaman durmayan bir animasyon — bunlar, trafiğiniz ister doğrudan ister altı ara sunucu üzerinden gelsin, aynı hatayı üretir. Yazının sonlarına doğru ele alınan, proxy ile ilgili gerçek bir durum vardır: ev bağlantıları gerçek gecikme süresi ekler, bu nedenle yerel testler için ayarlanmış varsayılan ayarlar yanlış hata mesajlarına neden olur. Ancak önce seçiciyi kontrol edin. Proxy yapılandırılmadığında testiniz aynı şekilde başarısız oluyorsa, sorun proxy değildir.
Altı Zaman Aşımı ve Varsayılan Ayarları
Öncelikle şunu anlamak gerekir ki, bunlar farklı varsayılan ayarlara sahip ayrı mekanizmalardır ve hangisinin tetiklendiğini bilmek, nereye bakmanız gerektiğini gösterir.
| Zaman Aşımı | Varsayılan | Ayar Yeri |
|---|---|---|
| Test | 30.000 ms | testConfig.timeout, test.setTimeout() |
| Expect | 5.000 ms | testConfig.expect.timeout, her bir doğrulama için seçenek |
| Action | Zaman aşımı yok | testOptions.actionTimeout, her çağrı için seçenek |
| Navigation | Zaman aşımı yok | testOptions.navigationTimeout, her çağrı için seçenek |
| beforeAll / afterAll kancası | 30.000 ms | test.setTimeout() kancanın içinde |
| Global | Yok | testConfig.globalTimeout |
Değerler Playwright zaman aşımı belgelerinden alınmıştır.
Bunlardan ikisi insanları şaşırtıyor.
Eylem ve gezinme için varsayılan olarak zaman aşımı yoktur. Bunlar yalnızca test zaman aşımı sınırıyla kısıtlanır. Dolayısıyla, koşullandırılmamış bir page.click() komutu, kalan test süresine kadar bekler ve aldığınız hata, tıklamadan ziyade testin zaman aşımına uğramasından kaynaklanır. Bu nedenle, kimse 30 saniyelik bir tıklama yapılandırmamış olsa bile mesajda 30000 ms yazmaktadır.
Global zaman aşımı için hiçbir varsayılan değer yoktur. Belgelerde bunun amacı, "her şey ters gittiğinde aşırı kaynak kullanımını önlemek" olarak açıklanmaktadır — CI'da bu ayarı yapmanızda fayda vardır; böylece takılan bir test dizisi, çalıştırıcıyı süresiz olarak meşgul etmek yerine başarısız olur.
“30000 ms’lik zaman aşımı aşıldı” Mesajının Asıl Anlamı
Bu mesaj, test zaman aşımını ifade eder ve test zaman aşımı bir teşhis değil, bir süre sınırıdır. İçinde yer alan bir işlem çok uzun sürdü ve mesaj, sorunun kaynağını değil, süre sınırını belirtir.
Her birinin gerçek neden olma sıklığına göre sıralanmış hali:
1. Bir konum belirleyici hiçbir şeyle eşleşmedi. Seçici yanlış, öğe görünmüyor ya da hesaba katmadığınız bir iframe veya gölge kökün içinde bulunuyor. Playwright, asla var olmayacak bir şeyi sabırla bekliyor.
2. Öğe mevcut ancak üzerinde işlem yapılamıyor. Bir overlay, çerez başlığı veya sabit başlık tarafından örtülmüş. Devre dışı bırakılmış. Hala animasyon halinde. Playwright, öğenin tıklanabilir hale gelmesini bekler, ancak bu asla gerçekleşmez.
3. Bir gezinme işlemi hiçbir zaman tamamlanmadı. Takılan bir ağ isteği, bir yönlendirme döngüsü veya kalıcı bağlantılara sahip bir sayfanın asla karşılamayacağı bir waitUntil koşulu — özellikle de networkidle.
4. Bir doğrulama koşulu hiçbir zaman doğru olmadı. Uygulamanın ulaşamadığı bir koşulu sorgulayan bir expect.
5. Test gerçekten çok fazla işlem yapıyor. Gerçek bir durumdur ve en az görülenidir.
Sıralama önemlidir çünkü çözümler tamamen farklıdır. Yalnızca 5. durum, zaman aşımı süresinin uzatılmasıyla çözülür. Diğer dört durumda ise zaman aşımı süresini uzatmak, aynı hatanın ortaya çıkması için daha uzun süre beklemek anlamına gelir.
Tıklamanızın Beklemesinin Nedeni: Eyleme Uygunluk
Bunu anlamak, kafa karışıklığının büyük bir kısmını ortadan kaldırır; çünkü Playwright’ın o otuz saniye boyunca ne yaptığını açıklar.
Eyleme geçirilebilirlik belgeleri, Playwright'ın "eylemleri gerçekleştirmeden önce öğeler üzerinde bir dizi eyleme geçirilebilirlik kontrolü uygulayarak bu eylemlerin beklendiği gibi çalışmasını sağladığını" ve "ilgili tüm kontrollerin geçmesini otomatik olarak bekledikten sonra istenen eylemi gerçekleştirdiğini" belirtir. Kontroller zamanında tamamlanmadığında, "eylem, 'TimeoutError' hatasıyla başarısız olur."
Gerekli kontroller eyleme göre farklılık gösterir ve bu farklılık, sorun teşhisinde yardımcı olur:
| Eylem | Gerekli kontroller |
|---|---|
click, dblclick, check, uncheck, tap, setChecked | görünür, kararlı, olayları alır, etkin |
hover, dragTo | görünür, kararlı, olayları alır |
fill, clear | görünür, etkin |
selectOption | görünür, etkin |
screenshot, selectText | görünür |
scrollIntoViewIfNeeded | kararlı |
blur, focus, press, pressSequentially, dispatchEvent, setInputFiles | yok |
Bu tablodan iki şey hemen göze çarpar.
Aynı öğe üzerinde fill çalışırken zaman aşımına uğrayan bir click, "kararlı" veya "olaylar alıyor" durumuna işaret eder — öğe hareket halindedir ya da üzerinde bir şey bulunmaktadır. Animasyonlar ve üst katmanlar bu durumun en yaygın nedenleridir.
Kontrol içermeyen eylemler hem bir kaçış yolu hem de bir uyarı işaretidir. Eğer locator.click() zaman aşımına uğrarken dispatchEvent('click') çalışıyorsa, hiçbir şeyi düzeltmemişsinizdir — gerçek bir kullanıcının da o öğeye tıklayamayacağını belirten kontrolü atlamışsınızdır. Bazen bu kabul edilebilir. Genellikle bu, testinizin artık algılamayı bıraktığı gerçek bir üst katman sorunu olduğu anlamına gelir.
Her Zaman Aşım Süresini Doğru Yerde Değiştirme
Yapılandırma birkaç düzeyde bulunur ve yanlış düzeye yerleştirilmesi kafa karıştırıcı sonuçlara yol açar.
Genel yapılandırma, playwright.config.ts
adresinde bulunur:
export default defineConfig({
timeout: 60_000,
globalTimeout: 60 * 60 * 1000,
expect: { timeout: 10_000 },
use: {
actionTimeout: 15_000,
navigationTimeout: 30_000,
},
});
Her birinin nerede yer aldığına dikkat edin. timeout
ve globalTimeout
en üst düzey yapılandırmadır; expect.timeout
, expect
altında yer alır; actionTimeout
ve navigationTimeout
ise use
altında yer alır, çünkü bunlar çalıştırıcı yapılandırması değil, test seçenekleridir. Bunların yanlış düzeye yerleştirilmesi sessizce göz ardı edilir.
Test başına:
test('slow one', async ({ page }) => {
test.setTimeout(120_000);
// ...
});
**test.slow()
** varsayılan zaman aşımını üç katına çıkarır — keyfi bir sayı seçmeden, gerçekten uzun olduğunu bildiğiniz bir test için iyi bir varsayılan değerdir.
Her bir doğrulama için:
await expect(page.getByRole('status')).toHaveText('Done', { timeout: 30_000 });
Her bir eylem için:
await page.getByRole('button', { name: 'Export' }).click({ timeout: 15_000 });
**beforeAll
ve afterAll
** içinde, ki bunların kendi 30 saniyelik zaman sınırları vardır, kanca (hook) içinde test.setTimeout()
işlevini çağırın.
Yavaş çalışan bir test için, onu kullanan her testin süre sınırını uzatmak yerine, test.extend()
içinde ona özel bir zaman aşımı süresi belirleyin:
export const test = base.extend<{ seeded: void }>({
seeded: [async ({}, use) => {
await seedDatabase();
await use();
}, { timeout: 60_000 }],
});
Genel ilke: sorunu çözen en dar kapsamı belirleyin. Tek bir yavaş testi karşılamak için genel test zaman aşımı süresini uzatmak, diğer tüm testlerin başarısızlık süresini uzatır ve bu da CI'da gerçek zaman kaybına neden olur.
Test Zaman Aşımına Ne Dahil Edilir
Sık sık yanlış anlaşılan bir konudur ve bu, “henüz hiçbir şey yapmadan” zaman aşımına uğrayan testleri açıklar.
Belgelerde açıkça belirtilmiştir: “Test fonksiyonu, fikstür kurulumları ve beforeEach kancaları tarafından harcanan süre, test zaman aşımına dahildir.”
Dolayısıyla, oturum açan, verileri hazırlayan ve sayfalar arasında gezinen bir beforeEach, test gövdenizin ihtiyaç duyduğu 30 saniyeyi tüketir. İlk satırında zaman aşımına uğramış gibi görünen bir test, kurulum aşamasında 28 saniye harcamış olabilir.
Fikstürler varsayılan olarak test zaman aşımını paylaşır; bu da farklı bir şekle bürünmüş aynı tuzaktır — kaynak tüketen bir fikstür, kendisine bağlı olan her testin zaman aşım kotasını tüketir. Her yerde test zaman aşımını artırmak yerine, yavaş fikstürlere kendi zaman aşım kotalarını verin.
Kaldırma işlemleri ayrıdır: Fikstür kaldırma işlemleri ve afterEach kancaları, test fonksiyonu tamamlandıktan sonra kendi zaman sınırlarına sahip olur; böylece yavaş bir kaldırma işlemi, testin süresini tüketmez.
Hata ayıklama açısından pratik sonuç: Bir test zaman aşımına uğradığında, hatanın işaret ettiği satırı değil, tüm zinciri (fixture'lar, beforeEach ve test gövdesi) inceleyin.
Sorunu Artırmadan Önce Teşhis Edin
Çoğu zaman aşım sorununu birkaç dakika içinde çözen bir işlem dizisi.
İzleme görüntüleyicisiyle çalıştırın. Bu, en değerli araçtır ancak yeterince kullanılmamaktadır:
npx playwright test --trace on
npx playwright show-trace trace.zip
İzleme, her eylemi, süresini, öncesi ve sonrasındaki DOM anlık görüntülerini ve ağ etkinliğini gösterir. Hiçbir şeyle eşleşmeyen bir konum belirleyici hemen göze çarpar; düğmenizin üstünde duran çerez başlığı da öyle.
Olayı izlemek istediğinizde "headed" ve "slowed down" modlarında çalıştırın:
npx playwright test --headed --debug
Konum belirleyicinin çözülüp çözülmediğini kontrol edin:
console.log(await page.getByRole('button', { name: 'Save' }).count());
Sıfır değeri, seçiciyle ilgili bir sorun olduğunu gösterir ve hiçbir zaman aşımı değeri bunu düzeltemez.
Bunun bir kararlılık sorunu olup olmadığını kontrol edin; bunu bir çözüm olarak değil, teşhis amaçlı olarak kontrol gerektirmeyen bir eylem kullanarak yapın. dispatchEvent('click')
adresi çalışırken click()
adresi zaman aşımına uğruyorsa, bir şey öğeyi kapatıyor veya hareket ettiriyor demektir.
**networkidle
'da bekleme olup olmadığını kontrol edin.** Analitik işaretçileri, web soketleri veya yoklama içeren sayfalar hiçbir zaman ağ boşta kalma durumuna ulaşmayabilir. Aslında önem verdiğiniz şeyi beklemeyi tercih edin:
await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible();
Hata mesajını baştan sona okuyun. Playwright'ın zaman aşımı hataları, konum belirleyiciyi, çözümlenen öğe sayısını ve hangi eyleme geçirilebilirlik kontrolünün beklemede olduğunu içerir. Bu son ayrıntı genellikle sorunun ne olduğunu doğrudan belirtir.
Zaman Aşım Sürelerini Uzatmak Genellikle Kararsızlığı Artırır
Sezgilere aykırı ama önemli bir nokta.
Kararsız bir test, sonucunun zamanlamaya bağlı olduğu testtir. Zaman aşımı süresini uzatmak, testin başarılı olma aralığını genişletir; böylece kararsızlık daha nadir hale gelir — ve buna bağlı olarak yeniden üretilmesi zorlaşır, teşhis edilmesi zorlaşır ve başarısızlık durumunda süreç daha yavaş ilerler.
Bununla birlikte, her başarısızlıkta bir bedel ödenir. 30 saniyelik zaman aşımı süresine sahip 200 testlik bir test grubunun tamamen başarısız olması en fazla 100 dakika sürer; 120 saniyede ise bu süre 400 dakikaya çıkar. Sürekli Entegrasyon (CI) ortamında bu, gerçek para ve gerçek bekleme süresi anlamına gelir.
Kararsızlığı gerçekten gideren şey:
Zamanı değil, durumu bekleyin. waitForTimeout neredeyse her zaman yanlıştır. Önem verdiğiniz koşulu doğrulayın ve Playwright’ın sorgulamasına izin verin.
Web öncelikli doğrulamaları kullanın. expect(locator).toBeVisible() otomatik olarak yeniden dener. expect(await locator.isVisible()).toBe(true) bir kez kontrol eder ve ilk başarısızlıkta hata verir — bu, ince ama çok yaygın bir kararsızlık kaynağıdır.
Overlay'leri deterministik bir şekilde ele alın. Çerez bildirimlerinin kaybolmasını ummak yerine, bunları bir fixture içinde kapatın.
Animasyonları devre dışı bırakın; animasyonların durmasını beklemek yerine, yapılandırmanızda mümkün olan yerlerde bunları devre dışı bırakın.
Ağın sessizleşmesini beklemek yerine, bağımlı olduğunuz belirli ağ yanıtını bekleyin.
Verileri stabilize edin. Paylaşılan değiştirilebilir duruma bağımlı testler, zaman aşımı ile çözülemeyen nedenlerden dolayı kararsızdır.
Ne zaman gerçekten zaman aşımı hatası vermelisiniz: İşlem gerçekten yavaşsa ve bunu aşmanın bir yolu yoksa — büyük bir dosya yüklemesi, oluşturulması bir dakika süren bir rapor, kasıtlı olarak kısıtlanmış bir ağ profili gibi. Bu durumlarda, zaman aşımı hatasını dar bir kapsamda, o testte veya o doğrulamada verin ve varsayılan ayarları olduğu gibi bırakın.
Proxy Üzerinden Çalışırken Oluşan Zaman Aşımları
Bir zaman aşımı hatasının meşru olduğu durum ve buna uygun yapılandırma.
Playwright, proxy ayarlarını ağ yapılandırması bölümünden alır:
export default defineConfig({
use: {
proxy: {
server: 'http://proxy.example.com:9000',
username: 'user',
password: 'pass',
},
},
});
Ya da bağlam başına; bu, farklı testlerin farklı çıkış konumlarına ihtiyaç duyduğu durumlarda tercih edilebilir:
const context = await browser.newContext({
proxy: { server: 'http://proxy.example.com:9000' },
});
Bunun üç pratik sonucu vardır.
Ev tipi proxy'ler gerçek gecikme süresi ekler. Trafik gerçek bir tüketici bağlantısı üzerinden dışarı çıkar, bu nedenle istek başına birkaç yüz milisaniyelik ek gecikme bir hata değil, normaldir. Seksen istek gönderen bir sayfa, bu gecikmeyi seksen kat artırır. Localhost'a göre ayarlanmış varsayılan değerler, bozuk proxy'ler gibi görünen ancak aslında sadece mesafeden kaynaklanan hatalara yol açar.
Doğru yaklaşım, tahminde bulunmak yerine ölçüm yapmaktır: test takımını proxy üzerinden çalıştırın, izleme zamanlamalarına bakın ve gözlemlediklerinize göre navigationTimeout
ve actionTimeout
değerlerini cömert bir marjla ayarlayın.
Bant genişliği asıl maliyettir ve tarayıcıda bu maliyet çok yüksektir. Playwright her görüntüyü, yazı tipini, komut dosyasını ve videoyu önceden yükler. GB başına 0,79 $ olan ölçümlü ev trafiğinde bu, harcadığınız diğer tüm masrafları gölgede bırakır. Gereksiz kaynak türlerini engellemek, elde edilebilecek en büyük tasarruftur:
await page.route('**/*.{png,jpg,jpeg,webp,gif,woff,woff2,mp4}', r => r.abort());
Bu, trafiği rutin olarak toplamın büyük bir kısmından azaltır ve bir yan etki olarak testlerinizi hızlandırır.
Engelleme, zaman aşımı değildir. Hedef bir doğrulama sayfası sunarsa, Playwright doğrulama sayfasında bulunmayan bir öğeyi beklerken zaman aşımına uğrar — bu durum tam olarak zaman aşımına benzer, ancak zaman aşımı değildir. Hata durumunda bir ekran görüntüsü alın ve gerçekte neyin görüntülendiğine bakın:
use: { screenshot: 'only-on-failure', trace: 'retain-on-failure' }
Bu, proxy'leri test etmenin neden önemli olduğu başlıklı yazımızda anlattığımız "sessiz hata" örneğidir: istek başarılı oldu, sayfa görüntülendi, ancak yanlış sayfaydı.
Sık Sorulan Sorular
Playwright’ta varsayılan zaman aşımı süresi nedir?
Testler ve beforeAll/afterAll kancaları için 30.000 ms, expect doğrulamaları için ise 5.000 ms'dir. Eylem ve gezinme zaman aşımları için varsayılan bir değer yoktur ve bunlar yalnızca test zaman aşımıyla sınırlıdır; bu nedenle, yavaş bir tıklama kendi sınırı yerine testin 30 saniyelik süresini bildirir.
Tek bir Playwright testinin zaman aşım süresini nasıl artırabilirim?
Testin içinde test.setTimeout(120_000) komutunu çağırın veya varsayılan değeri üç katına çıkarmak için test.slow() komutunu kullanın. Diğer tüm testlerin başarısızlık süresini uzatacak olan genel zaman aşım süresini artırmak yerine, bu yöntemleri tercih edin.
Öğe sayfada varken Playwright testim neden zaman aşımına uğruyor?
Genellikle eyleme açık olmadığı içindir. click, öğenin görünür, sabit, olayları alabilir ve etkin durumda olmasını gerektirir — bu nedenle, bir banner ile örtülü veya hala animasyon halinde olan bir öğe bulunur ancak asla tıklanmaz. Hata mesajı, hangi kontrolün beklemede olduğunu belirtir.
Test zaman aşımı ile beklenen zaman aşımı arasındaki fark nedir?
Test zaman aşımı, test fonksiyonu, fikstür kurulumları ve beforeEach kancalarının toplam süresidir ve varsayılan değeri 30 saniyedir. Beklenen zaman aşımı ise tek bir web-first doğrulamanın ne kadar süreyle sorgulanacağıdır ve varsayılan değeri 5 saniyedir. 5 saniye sonra başarısız olan bir doğrulama, test zaman aşımı değil, beklenen zaman aşımıdır.
Playwright’ta waitForTimeout kullanmalı mıyım?
Neredeyse hiçbir zaman. Sabit bir bekleme süresi ya çok kısa olur ve testi dengesiz hale getirir ya da çok uzun olur ve test takımını yavaşlatır — genellikle farklı makinelerde her ikisi de geçerlidir. Bunun yerine, zaman aşımına kadar otomatik olarak yeniden deneme yapan web-first doğrulama ile koşulun gerçekleşmesini bekleyin.
networkidle neden hiçbir zaman çözümlenmez?
Çünkü sayfa sürekli istek göndermeye devam eder — analitik işaretçileri, web soketleri, sorgulama, uzun süreli bağlantılar. networkidle'in sessiz bir ortam gerektirir ve birçok modern uygulama asla sessiz kalmaz. Bunun yerine, ilgilendiğiniz belirli öğeyi veya yanıtı bekleyin.
Zaman aşımını artırmak, tutarsız testleri düzeltir mi?
Bu, hataları gizler. Kararsızlık daha nadir hale gelir, yeniden üretilmesi zorlaşır ve hata vermesi daha uzun sürer; buna karşılık test dizisindeki her gerçek hata artık daha uzun sürer. Nedeni giderin — süre yerine durumu bekleyin, yeniden deneme onaylamaları kullanın, üst katmanları belirleyici bir şekilde kapatın ve animasyonları devre dışı bırakın.
Proxy kullanırken daha uzun zaman aşımlarına ihtiyacım var mı?
Genellikle ev tipi proxy’ler, bir sayfanın yaptığı birçok istek boyunca biriken gerçek istek başına gecikme süresi eklediğinden, gezinme ve eylemler için cevap evet’tir. Her şeyi önleyici olarak artırmak yerine, izleme özelliği etkinleştirilmiş halde proxy üzerinden bunu ölçün ve gözlemlediklerinize göre değerleri ayarlayın.
Sonuç
Mesajda, testin 30 saniyeyi aştığı belirtiliyor; ancak bu bir açıklama değil, sadece bir sınırdır. Testin içinde yer alan bir unsur, hiçbir zaman gerçekleşmeyen bir koşulu beklemiştir ve beş durumdan dördünde bu koşul, hiçbir şeyle eşleşmeyen bir seçici ya da hiçbir zaman işlem yapılabilir hale gelmeyen bir öğedir.
Dolayısıyla zaman kazandıran sıralama şöyledir: bekleyen eyleme geçirilebilirlik kontrolünü belirten hatanın tamamını okuyun; hata anındaki DOM'u gösteren izleme dosyasını açın; konum belirleyicinin çözümlendiğini doğrulayın; ve ancak o zaman sayıyı dikkate alın. Zaman aşımı hatası vermek, tam olarak tek bir neden için doğru çözümdür — gerçekten bütçeden daha uzun süren bir işlem — ve diğer dört durum için yanlış çözümdür; bu durumlarda, daha yavaş bir hata ile sonuçlanır.
Zaman aşımı ayarlayacağınız zaman, bunu dar bir kapsamda yapın. Test başına, doğrulama ifadesi başına, test düzeneği başına. Tek bir yavaş yüklemeyi telafi etmek için genel varsayılan değerleri şişirmek, test dizisindeki her hatayı daha maliyetli hale getirir ve CI süresi, bir daha asla geri gelmeyen tek kaynaktır.
