Özel şeyler testler için iç / genel olarak mı yoksa PrivateObject gibi bir tür kesmek mi kullanmak istersiniz?


26

Kod sınama konusunda oldukça acemiyim ve daha assertönce bir fahişeydi. Birim testinde beni endişelendiren şeylerden biri, çoğunlukla, aksi halde olacak olan alanları public( onları çözmek için, yöntemler yerine, vb. internal) Yapmanızı gerektirir .privatereadonlyprivateprotected virtual

Kısa süre önce , bir nesnede herhangi bir şeye yansıtma yoluyla ulaşmak için PrivateObject sınıfı gibi şeyleri kullanarak bunu önleyebileceğinizi keşfettim . Ancak bu, testlerinizi daha az bakım gerektirebilir hale getirir (derleme zamanı yerine yürütmede işler başarısız olur, basit bir yeniden adlandırma tarafından kırılır, hata ayıklaması daha zordur ...). Bu konudaki fikriniz nedir? Birim testinde erişim kısıtlamasıyla ilgili en iyi uygulamalar nelerdir?

düzenleme: örneğin, diskteki bir dosyada önbelleği olan bir sınıfınız olduğunu ve sınamalarınızda bunun yerine belleğe yazmak istediğinizi düşünün.


2
Python millet sadece halk var. Onlar mutlular. Neden endişe? Neden her şeyi halka açıklamıyorsun?
S.Lott

12
Çünkü bu, en iyi dillerin çoğunda en iyi uygulamalardan uzaktır. Asıl cevap, iyi arayüzler kullanmaktır ve bu sayede test yapmak için sahte nesneler kullanabilirsiniz.
Rig

2
@Rig: Python bir üst dil değil mi? İlginç.
S.Lott,

7
"en iyi dillerin çoğunda en iyi uygulamalardan uzaktır", mantıksal olarak ima etmez (ya da hatta bundan bahseder) "Python bir üst dil değildir".
Mike Nakis

1
Kesin olarak, bu bir ana dildir, ancak en üst dillerin çoğu Python değildir ve uygun kapsam belirleme konusunda onay vermiştir. Kendi ifademin arkasında duruyorum. Değişkenlerin kapsamı muhafaza etmesini sağlarken yüksek derecede test edilebilir yazılım yapmak için tasarlanmış desenler vardır. Python programcıları bile gördüklerimin ön ekleriyle kapsam taklit etme eğilimindedir.
Rig

Yanıtlar:


36

Asla yapmamalısın

yapmak public(ya da en azından internal) olurdu alanlara privatesökebilmenizi, aksi readonlyonları, marka privateyöntemlerinin protected virtualyerine

Özellikle bir alanın okunmaması, değişmez bir nesneyi değiştirilebilir hale getirebilir ve bu bir felaket olur.

Testleriniz nesnelerinizi kara kutular ( Vikipedi ) olarak kabul etmeli, bu, uygulamalarının ayrıntılarıyla değil, yalnızca nesnelerin ortak arayüzü ile ilgilenmeleri gerektiği anlamına gelir.

Bir nesne ortak arayüzü kullanılarak yeterince test edilemezse, arayüzünü test etmeyi kolaylaştıracak resmi ve faydalı uzantılar sunmanın yollarını bulmanız gerekir. Örneğin, yalnızca bir çift Kayıt / Kayıt Silme yöntemine sahip bir kayıt sistemi, eldeki uygulama için gerekli olmasa bile, bir IsRegistered yönteminden faydalanabilir; Yine de, arayüze yönelik resmi ve faydalı bir eklentidir ve bu arada, test için uygun olacaktır.

Önemli olan, nesnenin uygulamasını değiştirmenin, birim testini değiştirmenizi gerektirmemesi gerektiğidir. Teoride, birim testini bir kez yazabilmeli ve daha sonra birden fazla programlayıcıdan birim testiyle çalışmak için test edilecek nesnenin tamamen farklı uygulamalarını kodlamasını istemeniz gerekir.


2
Kesinlikle! Yansıma veya kırma olmadan test edemezseniz, API veya tasarımınızda bir hata yapmış olabilirsiniz.
Şahin

Testlerde alay etmeye yardımcı olacak privateyöntemler yapmanın protected virtualkötü bir uygulama olarak kabul edildiğini mi söylüyorsunuz ?
Robula

1
@Robula Kitabımda evet. Testlerimi üretim koduyla aynı pakete bile yazmıyorum, çünkü herkese açık olmayan üyelere erişemiyorum. Ben de alay kullanmıyorum. Elbette alay kullanmanız gerekiyorsa, alaycayı kolaylaştırmak için ne gerekiyorsa yapmanız gerekecektir, bu nedenle korumalı sanal birçok durumda pratik bir uzlaşma olabilir. Ancak ideal olarak bir tasarımın alaylara ihtiyacı yoktur, sadece alternatif uygulamalar vardır ve ideal olarak sınama, beyaz kutu sınaması değil, kara kutu sınamasıdır;
Mike Nakis

13

C # ile InternalsVisibleToAttribute, test grubunuzun test internalettiğiniz montajdaki sınıfları görmesine izin vermek için kullanabilirsiniz . Bunu zaten biliyor gibisin.

Çoğu durumda sadece meclisimin genel API'sini test etmekle ilgileniyorum. Bazı birimlerin beyaz kutu testini yapmak istediğim bir durumda, kodu bir internalsınıfa taşıyorum ve onu publicbu sınıfın bir yöntemi haline getiriyorum . Sonra o sınıf için bir birim testi kodlayabilirim.

Bu, bağımlılık enjeksiyonuna ve strateji modeline çok iyi borç veriyor. Yöntemi bir arayüze soyutlayabilir, arayüzü üst nesnenizin yapıcısına enjekte edebilir ve sadece üst delegenin uygun şekilde delegasyon yaptığını test edebilirsiniz. Ardından alt nesnenin uygun şekilde davrandığını test edebilirsiniz. Bu her şeyi daha modüler kılar.


8

Deneyimlerime göre, sınıfınızın iç kısımlarını test için özel olarak göstermemek en iyisidir. Testin yazılmasını kolaylaştırmak için bu görünebilir. Test, sınıfınızın ilk müşterisidir, bu nedenle sınıfınızı genel arayüzü üzerinden test etmek zorsa, sınıfınızı başka yerlerde de kullanmak zor olacaktır.

Sınıfın genel API'siyle test etmenin ne kadar kolay olduğu, sınıfın ne kadar kolay kullanılacağına dair geri bildirimdir. Testleri kısmen sınıfınızın kullanımını prototiplemenin bir yolu olarak düşünün.

Testinizin neden genel API ile erişilemeyen sınıf hakkında bir şeyler hissetmesi gerektiğini düşünmeye çalışın. Belki de sınıfınız çok fazla şey yapıyor ve bunun yerine bir grup işbirliği sınıfına ayrılması gerekiyor? Ardından, test edilen sınıfın ne yaptığını hissetmek için ortak çalışma sınıflarından bazıları ile alay edebilirsiniz.

Bağımlılık inversiyon prensibini uygulamaya çalışın ve sınıflarınız arasında testlerinizde alay edebileceğiniz arayüzler sunun. Ortak çalışanlara denetimin tersini kullanarak testinize sağlayabilirsiniz .

Ayrıca , sınıf arayüzünüzü, doğru bilginin açığa çıkarıldığı ve geri kalanının gizlendiği sağlam, gevşek bir şekilde bağlı bir şekilde yapılandırılmasına yardımcı olmak için "sorma" ilkesini uygulamayı düşünün .


6

Şahsen kodumu bırakmayı tercih ediyorum olabildiğince saf olarak test ediyorum ve test kodu kesmek istiyorsa (ve C ++ kötü işaretçilerde vb.) Bunu yapmaktan mutlu olurum.



1
Kabul ediyorum, bu şekilde yapmanın yolu. Çirkinliği test kodunda tutun, hiçbir şeyden zarar veremez.
Alan Delimon

@AlanDelimon Daha sonraki bakım programcılarının aklına zarar vermeyebilir mi?
flamingpenguin

1
@flamingpenguin çirkin kodu her yerde programcılara zarar verebilir; ancak çirkin test kodu muhtemelen sınıfı değiştiren insanları etkileyeceği için sadece zararsız olanları etkilemeyeceğinden daha az zarar verecektir.
Dan Neely

2
@flamingpenguin Olabilir, ama bir yere çirkin bir kod koymak zorunda kalırsanız, modifikasyona ihtiyaç duymanın ve uygulamanın bir parçası olmanın daha az muhtemel olduğu bir birim testinde de olabilir.
Alan Delimon

5

Kodunuzun görünürlüğü, birim testlerinizle ilgisi yoktur!

Yöntemlerinizi test etmekten sakınmak amacıyla değil, herkese açık testlere maruz bırakmamak için özel kılıyorsunuz, değil mi? Bu sizin uygulama için burada gerekli olan testlerdir - kodunuzu kanıtlayan bu sunucu, ancak bunlar sizin kodunuz değildir .

Gizli (özel veya dahili) yöntemlere ve özelliklere erişim sağlamanın birçok yolu vardır. Pek çok test çerçevesi ve IDE (örneğin, Visual Studio), burada erişim için gereken her şeyi üreterek sizi destekler, yalnızca test durumlarınızı yazmanız gerekir. Peki neden endişeleniyorsun? Kodunuzu temiz ve düzenli tutmak daha iyi.

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.