Sonunda tutarlı bir hizmete karşı nasıl test yazabilirim?


17

Sonunda tutarlı bir veri deposu olan Google App Engine Datastore'un üzerine bir hizmet oluşturuyorum. Benim uygulama için, bu iyi.

Ancak, PUT nesnesi ve sonra GET nesnesi gibi şeyler yapan testler geliştiriyorum ve döndürülen nesnenin özelliklerini kontrol ediyorum. Ne yazık ki, veri deposu nihayetinde tutarlı olduğundan, bu basit testler tekrarlanamaz.

Sonunda tutarlı bir hizmeti nasıl test edersiniz?


2
İlk etapta neden harici bir servise karşı tekrar üretilebilirliği beklediğinizi test ediyorsunuz?

... ve aslında neyi test etmeye çalışıyorsunuz? senin kodun? veya Google'ın?

5
Tüm sistemi test ediyorum. Yani, birim testleri değil, entegrasyon testleridir.
Doug Richardson

3
How can I reproducibly test an eventually consistent service? - Yapamazsın. "Tekrarlanabilir" kelimesini veya "sonunda" kelimesini kaldırmanız gerekir. ikisine birden sahip olamazsınız.
Robert Harvey

1
Sonunda tutarlı olursa, tekrarlanabilir olsun veya olmasın, herhangi bir sonuç başarılı olacaktır. Uygulamanız için iyi olduğunu zaten söylediniz, peki gerçekten neyi test ediyorsunuz? Olasılık? GAE ile entegrasyon? Senin kodun?
Laiv

Yanıtlar:


16

İşlevsel testlerinizi tasarlarken işlevsel olmayan gereksinimleri göz önünde bulundurun - hizmetinizde "x içinde tutarlı (saniye / dakika / vb.)" İşlevsel olmayan bir gereksinim varsa, PUT isteklerini çalıştırın, x bekleyin ve ardından GET isteklerini çalıştırın.

Bu noktada, veriler henüz 'ulaşmadı' ise, PUT isteğinin gereksinimlerinize uygun olmadığını düşünebilirsiniz.


7

Testlerinizin hızlı ve tutarlı olmasını gerçekten istiyorsunuz. Sonunda tutarlılık nedeniyle zaman zaman başarısız olabilecek testler oluşturmaya başlarsanız, başarısız olduğunda testi göz ardı edersiniz ve ne işe yarar?

PUT ve GET isteklerini işleyen, ancak tutarlı hale getirmek için ek bir işlemi olan sahte bir hizmet oluşturun. O zaman testiniz:

datastore.do_put(myobj);
datastore.make_consistent();
validate(datastore.do_get(), myobj);

Bu, GET PUT nesnesini başarıyla aldığında yazılımınızın davranışını test etmenizi sağlar. Ayrıca, hizmetin tutarlı olmaması nedeniyle GET nesneyi (veya doğru nesneyi) bulamadığında yazılımınızın davranışını test etmenizi sağlar. Sadece aramayı bırak make_consistent().

Gerçek hizmetle etkileşime giren testlere sahip olmaya değer, ancak asla% 100 güvenilir olmayacakları için normal geliştirme iş akışınızın dışında çalışmalıdırlar (örneğin, hizmet çalışmıyorsa). Bu testler aşağıdakiler için kullanılmalıdır:

  1. bir PUT ile müteakip bir GET'in tutarlı hale gelmesi arasındaki ortalama ve en kötü vaka süresi metriklerini sağlamak; ve
  2. Sahte hizmetinizin gerçek hizmete benzer şekilde davrandığını doğrulayın. Bkz. Https://codewithoutrules.com/2016/07/31/verified-fakes/

6

Tamam yani. "Neyi Test Ediyorsunuz" anahtar soru.

  • Google işlerinin işe yaradığını varsayarak içsel mantığımı test ediyorum

Bu durumda, google hizmetleri ile alay etmeli ve her zaman bir yanıt vermelisiniz.

  • Google'ın üreteceğini bildiğim geçici hatalarla başa çıkabildiğimi test ediyorum

Bu durumda, google hizmetleri ile alay etmeli ve her zaman doğru hatayı doğru yanıttan önce döndürmelisiniz

  • Ürünümün gerçek google hizmeti ile çalışacağını test ediyorum

Gerçek google hizmetlerini enjekte etmeli ve testi çalıştırmalısınız. Fakat! Test ettiğiniz kodun içinde Geçici Hata işleme (yeniden deneme) bulunmalıdır. Yani tutarlı bir yanıt almalısınız. (google çok kötü davranmadıkça)


Mock önerisi için +1 - Yapabilseydim ek seçenekler için daha fazla oy verirdim.
mcottle

6

Aşağıdakilerden birini kullanın:

  • PUT'dan sonra, başarılı olana kadar GET N kez tekrar deneyin. N denedikten sonra başarı olmazsa başarısız olur.
  • PUT ve GET arasında uyku

Ne yazık ki, bu tekniklerin her ikisi için sihirli değerler (N veya uyku süresi) seçmelisiniz.


1
Açıklığa kavuşturabilir misiniz? Bu alternatifler mi yoksa tamamlayıcı mı? Bence onların alternatif olduğunu söylemek istiyorsun - ve ben böyle düşünüyorum. Ama belki yanılıyorum.
Robin Green

1
Doğru, onların alternatif olmalarını istedim.
Doug Richardson

2

Anladığım kadarıyla, Google Cloud veri deposu hem tutarlı hem de sonunda tutarlı sorgulara izin veriyor .

Takas, oldukça tutarlı sorguların oldukça ciddi oranda sınırlı olmasıdır (test sırasında yaşayabileceğiniz bir şey).

Bir olasılık, test amacıyla güçlü bir tutarlılık sağlayabilen sorgularınızı bir sarıcı içinde veri deposuna koymak olabilir.

Örneğin, start_debug_strong_consistency()ve adlı yöntemleriniz olabilir end_debug_strong_consistency().

Başlangıç ​​yöntemi, sonraki tüm sorgular için bir ata anahtarı olarak kullanılabilecek bir anahtar oluşturur ve bitiş yöntemi anahtarı siler.

Test ettiğiniz gerçek sorgularda yapılan tek değişiklik, setAncestor(your_debug_key)bu anahtar mevcutsa aramak olacaktır.


1

Teoride güzel olan ancak her zaman pratik olmayabilecek bir yaklaşım, sistemdeki tüm yazma işlemlerini sınama idempotent yapmaktır . Bu, test kodunuzun bir şeyleri sabit bir sırayla test ettiği varsayılarak , beklediğiniz sonucu elde edene kadar tüm okumaları ve tüm yazma işlemlerini tek tek deneyebilirsiniz , test kodunda tanımladığınız bir zaman aşımı süresi geçene kadar yeniden deneyebilirsiniz . Yani, A1 işini yapın, gerekirse sonuç B1 olana kadar yeniden deneyin, ardından A2 işini yapın, gerekirse sonuç B2 olana kadar yeniden deneyin vb.

Daha sonra yazma işlemlerinin ön koşullarını kontrol etmek için uğraşmanıza gerek yoktur, çünkü yazma işlemleri bunları sizin için zaten kontrol edecektir ve başarılı olana kadar tekrar deneyin!

Tüm sistem yavaşlarsa artırılabilen aynı "varsayılan" zaman aşımlarını kullanın ve özellikle yavaş işlemleri yeniden denerken varsayılan değerleri ayrı ayrı geçersiz kılın.


1

Google App Engine Veri Deposu gibi bir hizmet, küresel olarak yayılmış çeşitli varlık noktalarında (POP) veri çoğaltmasına dayanır. Sonunda tutarlı bir hizmet için herhangi bir tümleştirme testi, söz konusu hizmetin KOK'lar arasında çoğaltma oranının gerçekten bir testidir. İçeriğin, belirli bir hizmetteki her POP'a yayılma oranı, çoğaltma yöntemi ve çeşitli Internet aktarım sorunları gibi bir dizi faktöre bağlı olarak hizmet içindeki her POP ile aynı olmayacaktır - bunlar iki örnektir (en azından büyük bir CDN için çalışırken benim deneyimim buydu).

Bir nesnenin çoğaltmasını belirli bir platformda etkili bir şekilde test etmek için, testi, hizmetin POP'larının her birinden özellikle yakın zamanda yerleştirilen aynı nesneyi isteyecek şekilde ayarlamanız gerekir. KOK listesini bir ila beş kez veya KOK listenizdeki tüm KOK'lar nesneye sahip olduğunu bildirene kadar test etmenizi öneririm. Ayarlayabileceğiniz testi gerçekleştirmek için bir dizi aralık aşağıda verilmiştir: veri deposuna yerleştirdikten sonra 1, 5, 60 dakika, 12 saat, 25 saat. Anahtar, belirli bir hizmetin nesneleri genel olarak çoğaltma yeteneğini anlamak için sonuçları daha sonra gözden geçirmek ve analiz etmek üzere her aralıkta günlüğe kaydetmektir. Genellikle veri deposu hizmetleri yerel bir kopyayı POP'a yalnızca yerel olarak istendiğinde çeker [yönlendirme BGP protokolü üzerinden yapılır, bu nedenle testiniz belirli bir POP için nesnenin belirli bir platform için global olarak geçerli olmasını istemek zorundadır] . Google'ın Veri Mağazası söz konusu olduğunda, testinizi belirli bir nesneyi "33 ülkede 70'ten fazla varlık noktasından" sorgulamak üzere ayarlamaya çalışacaksınız; Google Destek'ten POP'a özgü adres URL'si listesini almanız gerekir [ref:https://cloud.google.com/about/locations/ ] veya Google çoğaltma için Hızlı şekilde kullanıyorsa, Hızlı Destek [ https://www.fastly.com/resources ].

Bu yöntemin birkaç avantajı: 1) Belirli bir hizmetin çoğaltma platformu hakkında fikir sahibi olacak, sağlamlıklarını ve zayıf noktalarını küresel ölçekte [entegrasyon testi sırasında olduğu gibi] tanıyacaksınız. 2) Hangi nesneyi test ederseniz edin, içeriği ısıtmak için bir araca sahip olursunuz [belirli bir yerel POP'da kopyayı oluşturan ilk isteği yapın] - böylece müşterilerinizin talep etmeden önce içeriğin global olarak yayılmasını sağlamanın bir yolunu sunar dünyanın herhangi bir yerinde.


0

Google App Engine Veri Deposu ile deneyimim var. Yerel olarak çalışan, şaşırtıcı bir şekilde, genellikle "tutarlı" olmaktan çok "nihayetinde" olur. En basit örnek: yeni bir varlık oluşturun ve sonra onu alın. Genellikle son 5 yılda, yerel olarak çalışan SDK'nın yeni varlığı hemen bulamadığını, ancak yaklaşık yarım saniye sonra bulduğunu gördüm.

Ancak, gerçek Google sunucularına karşı koşarken, bu davranışı görmedim. Datastore istemcinizi her zaman yanlarında aynı sunucuya karşı çalıştırmaya çalışırlar, bu nedenle genellikle değişiklikler hemen sorgulara yansıtılır.

Entegrasyon testleri için tavsiyem, onları gerçek sunuculara karşı çalıştırmaktır ve sonuçlarınızı almak için muhtemelen herhangi bir sahte yoklama veya gecikme yapmanız gerekmeyecektir.


Bu uygun olsa da, birden çok uygulama sunucusunu içeren ince kırılmaların entegrasyon testlerinizde fark edilmemesine neden olabilir. Yerel sunucu sonunda iyi bir nedenle tutarlı hale sanırım!
Robin Green
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.