Otomasyon QAKıdemli Otomasyon QA Mühendisi

Gerçek zamanlı iki yönlü WebSocket iletişim protokolleri için tam otomatik bir doğrulama çerçevesi geliştirin; bu çerçeve tam mesaj iletim anlamlarını garanti etmeli, trafik kontrolü yoluyla ağ bölünmesi senaryolarını simüle etmeli ve heterojen istemci uygulamaları arasında ikili yük verisi serileştirmesini doğrulamalıdır; ayrıca yatay ölçeklendirilmiş CI ortamlarında katı test izolasyonunu sağlamalıdır.

Hintsage yapay zeka asistanı ile mülakatları geçin

Sorunun cevabı

Sorunun tarihi

WebSocket testi, basit HTTP istek-yanıt modellerinden sürekli bağlantı doğrulamasına evrildi. Erken otomasyon, soketleri kara kutu HTTP yükseltmeleri olarak ele alarak durumlu akış anlamlarını göz ardı etti. Modern gerçek zamanlı uygulamalar, çerçeveler üzerinde Protobuf gibi ikili protokollerin ve TCP bozulması altında dayanıklılık garantilerini doğrulamayı gerektirir. Soru, mesaj tüketimindeki yarış koşulları nedeniyle testlerin ara sıra başarısız olduğu halde, dalgalı CI boru hatlarını gözlemlemekten ortaya çıktı. Ekipler, özsel olarak asenkron, itme tabanlı mimarilerle belirleyici iddiaları uzlaştırmakta zorlandılar.

Problem

Temel sorun, belirleyici olmayan beklemeler oluşturmadan zamansal özellikleri (sıralama, gecikme) doğrulamaktır. WebSocket bağlantıları, paralel test yürütülmesiyle çatışan durumlu oturumlar tutar; bu da port çakışmalarına ve paylaşımlı abonelik kirlenmesine neden olur. İkili yükler, JSON iddialarından farklı olan şema-bilinçli ayrıştırma gerektirir, bu doğrulamayı karmaşıklaştırır. Ağ dayanıklılık testi, uygulama kodunu değiştirmeden taşıma katmanında hata enjeksiyonu gerektirir. Geleneksel anket tabanlı Selenium veya REST Assured kalıpları, sunucu itme akışları yerine istek-yanıt döngülerini varsayar.

Çözüm

Mesaj akışlarını sanal zaman yetenekleriyle gözlemlenebilir diziler olarak modellemek için Project Reactor veya RxJava kullanarak reaktif bir test şeması tasarlayın. Her testi, ayrılmış bir Docker ağ alanında izole ederken, ağ bölünmelerini ve gecikmeyi simüle etmek için TestContainers ile Toxiproxy kullanın. Her testin benzersiz bir oturum tanımlayıcısı oluşturduğu bir korelasyon UUID stratejisi uygulayın; bu, paralel çalışanlar arasında mesaj yönlendirme izolasyonunu sağlar. İkili doğrulama için, Protobuf şemalarına karşı ayrıştırma yaptıran ByteBuf eşleştiricilerine veya özel Hamcrest eşleştiricilerine kullanın. Sinyal sayıları ve sıralama ile ilgili açık beklentilerle StepVerifier kullanarak testleri yürütün.

@Testcontainers public class WebSocketResilienceTest { @Container private static final ToxiproxyContainer toxiproxy = new ToxiproxyContainer("ghcr.io/shopify/toxiproxy:2.5.0"); private WebSocketClient client; private ToxiproxyClient proxyClient; @BeforeEach void setUp() { client = new ReactorNettyWebSocketClient(); proxyClient = new ToxiproxyClient(toxiproxy.getHost(), toxiproxy.getControlPort()); } @Test void shouldMaintainMessageOrderingUnderNetworkLatency() throws IOException { Proxy proxy = proxyClient.createProxy("ws", "0.0.0.0:8666", "host.testcontainers.internal:8080"); proxy.toxics().latency("latency", ToxicDirection.DOWNSTREAM, 2000); StepVerifier.create( client.execute( URI.create("ws://" + toxiproxy.getHost() + ":" + toxiproxy.getMappedPort(8666) + "/stream"), session -> session.receive() .map(WebSocketMessage::getPayloadAsText) .filter(msg -> msg.contains("sequence")) .take(3) .collectList() ) ) .assertNext(messages -> { assertThat(messages) .extracting(json -> JsonPath.read(json, "$.sequence")) .containsExactly(1, 2, 3); }) .verifyComplete(); } }

Hayat hikayesinden

Yüksek frekanslı bir ticaret platformu, piyasa verisi akışları için REST anketinden WebSocket akışına geçiş yapıyordu. QA ekibi, piyasa dalgalanmaları sırasında bile fiyat güncellemelerinin doğru zamansal sıralamada geldiğini doğrulamalıydı ve bu da 10k+ mesaj/saniye gerektiriyordu. Mevcut REST setinin senaryoları doğrulaması sekiz dakika sürerken, WebSocket'ler bunu birkaç saniyede halledebiliyordu ve otomasyon çerçevesinin tamamen yeniden yapılandırılmasını gerektiriyordu.

Başlangıç uygulaması, mesajların gelmesi için beklemek amacıyla Thread.sleep() kullanıyordu; bu da 30 saniyelik test setlerine ve %40 lik bir hata oranına yol açıyordu. Paralel yürütme, testlerin paylaşılan Redis pub/sub hatlarından birbirlerinin mesajlarını tüketmesine neden oldu. İkili Protobuf yükleri Base64 dizeleri olarak karşılaştırılıyordu; bu, tekrarlanan öğelerde belirleyici olmayan alan sıralaması nedeniyle başarısızlıklara yol açıyordu.

Ekip, mesajları toplamak ve zaman aşımı ile anket yapmak için LinkedBlockingQueue kullanmayı düşündü. Bu, basit bir iddia mantığı sağladı ancak belirleyici olmayan gecikmeler getirdi. Testler yavaş kalmaya devam etti ve kuyruk boşaltmadaki yarış koşulları, mesajların tüketimden daha hızlı geldiği durumlarda ara sıra başarısızlıklar ortaya çıkardı. Yaklaşım, yalnızca nihai alımın doğrulanmasını sağladı; gerçek sıralama mantığını doğrulamadı.

WireMock veya MockWebServer kullanarak yakalanan WebSocket çerçevelerini tekrar oynatmak, belirleyici bir yürütme sağladı ve hızlı geri bildirim sundu. Ancak, TCP paket kaybı veya yeniden bağlantı mantığını yakalamanın gerçek dayanıklılık sorunlarını çözemedi. Mocklar, uygulama sunucusundaki gerçek Netty işleyici mantığını test etmediği için yeniden bağlantı hataları üretim ortamına geçiş yaptı.

Zamanı programatik olarak manipüle etmek için Reactor'ın TestScheduler'ını uygulamakla birlikte, Toxiproxy arkasındaki gerçek WebSocket sunucusunu çalıştıran TestContainers kullanmak, milisaniye hızında çalışırken gerçek ağ davranışlarını doğrulamayı sağladı. Sanal zaman zamanlayıcısı, 5 dakikalık zaman aşımı pencerelerini 50 ms altında test etmeyi sağladı; bu arada Toxiproxy, hassas gecikme ve bant genişliği sınırları ekledi. Bu yaklaşım daha fazla başlangıç ayarı gerektiriyordu, ancak en yüksek doğruluğu sağlıyordu.

Ekip, üretim sadakatini korurken yürütme hızını feda etmemeyi sağladığı için reaktif sanal zaman yaklaşımını seçti. Mocklardan farklı olarak, aslında Netty boru hattını ve yeniden bağlantı işleyicilerini doğruladı. Engelleyici kuyruklardan farklı olarak, Flux dizi operatörleri aracılığıyla belirleyici sıralama iddiaları sağladı. Docker ağlarının sağladığı izolasyon, paralel yürütme çatışmalarını ortadan kaldırdı.

Test yürütme süresi, her set için 4 dakikadan 12 saniyeye düştü. Hatalılık, üç aylık CI çalıştırmaları boyunca sıfıra düştü. Çerçeve, uygulamanın TCP yeniden bağlantı olaylarından sonra mesajları tekrar çoğaltmayı başaramadığı kritik bir hatayı yakaladı; bu, önceki manuel testlerde atlanmıştı. Çözüm, port çakışmaları olmadan 50 paralel CI çalışanına ölçeklendi.

Adayların genellikle atladığı noktalar

Paralel WebSocket testleri yürütülürken mesaj çapraz kontaminasyonunu nasıl önlersiniz?

Adaylar genellikle istemci örneği üzerinde synchronized blokları veya ReentrantLock kullanmayı önerir. Bu, yürütmeyi seri hale getirir ve paralel CI amacını bozar. Doğru yaklaşım mimari izolasyona dayanır: her test sınıfı, kendi TestContainer'ını oluşturur ve ayrılmış bir ağ alanı ile dinamik port tahsisi sağlar. Her test yalnızca benzersiz korelasyon tanımlayıcısıyla etiketlenmiş mesajlara abone olduğu için UUID tabanlı yönlendirme anahtarları kullanın. Bu, hiçbir paylaşılan durumu sıfır performans darboğazı olmadan sağlar.

WebSocket ikili çerçevelerini Base64 dizeleri olarak karşılaştırmanın neden yanlış negatiflere yol açtığını ve ikili yüklerin nasıl doğrulanacağı?

Protobuf veya MessagePack yüklerinin Base64 kodlaması, uygulamalar arasında değişebilen kablo-formatı meta verilerini (alan sıralaması, bilinmeyen alanların tutulması) içerir. Dize karşılaştırması, anlamsal olarak benzer mesajların farklı ikili temsillere sahip olduğunda başarısız olur. Bunun yerine, resmi Protobuf derleyicisini kullanarak ByteBuf'u oluşturulmuş Java/Kotlin sınıfına ayrıştırın; ardından AssertJ'nin yinelemeli karşılaştırması ile derin alan alan karşılaştırması yapın. Bilinmeyen alanlar için, proto eşdeğerliğini doğru bir şekilde ele alan ProtoTruth (Google'ın Truth kütüphanesi uzantısı) kullanın.

Uygulama güvenlik duvarı kurallarını değiştirmeden WebSocket testlerinde nasıl bir ağ bölünmesini simüle edersiniz?

iptables veya uygulama kodunu değiştirmek, kök ayrıcalıkları gerektirir ve ortam kaymasına neden olur. Adaylar genellikle Toxiproxy veya Pumba (Docker için Kaos Test aracı) atlayarak bu görevleri yerine getirir. Bu araçlar, test ağındaki yan konteynerler olarak çalışır ve REST API'ları aracılığıyla gecikme, bant genişliği sınırlamaları ve bağlantı sıfırlamaları eklemeye olanak tanır. WebSocket istemcisini proxy uç noktasında bağlanacak şekilde yapılandırın. Test sırasında, toksik uç noktayı arayarak bağlantıları kesmeyi veya %100 paket kaybı indüklemeyi sağlayın; ardından, istemcinin beklenen yeniden bağlantı gerileme stratejisini tetiklediğini ve doğru mesaj sıralama tanımlayıcısıyla devam ettiğini doğrulayın.