Özel yöntemleri Birim test etme gereksinimi nasıl önlenir


15

Özel yöntemleri test etmeniz gerekmediğini biliyorum ve eğer ihtiyacınız varsa, orada dışarı çıkmayı bekleyen bir sınıf olabilir.

Ancak, ben sadece bir kamuoyu arayüzlerini test edebilmek için bir gazilyon dersi almak istemiyorum ve birçok ders için sadece kamusal yöntemleri test edersem çok bağımlılıklarla alay etmek zorunda kaldığımı ve birim testlerinin muazzam ve takip edilmesi zor.

Herkesi test ederken özel yöntemlerle alay etmeyi ve özel olanları test ederken dış bağımlılıkları alay etmeyi tercih ederim.

Ben deli miyim?


Kapsamlı bir birim testi, belirli bir sınıfın tüm özel üyelerini örtülü olarak kapsamalıdır, çünkü onları doğrudan arayamazken, davranışlarının çıktı üzerinde hala bir etkisi olacaktır. Eğer yapmazlarsa neden ilk etapta oradalar? Ünite testinde, önem verdiğiniz şeyin sonuca nasıl geldiğine değil, sonucuna dikkat edin.
GordonM

Yanıtlar:


24

Kısmen haklısın - doğrudan özel yöntemleri test etmemelisin . Bir sınıftaki özel yöntemler bir veya daha fazla genel yöntemle çağrılmalıdır (belki dolaylı olarak - bir genel yöntem tarafından çağrılan özel bir yöntem diğer özel yöntemleri çağırabilir). Bu nedenle, genel yöntemlerinizi test ederken, özel yöntemlerinizi de test edersiniz. Denenmemiş kalan özel yöntemleriniz varsa, test durumlarınız yetersizdir veya özel yöntemler kullanılmaz ve kaldırılabilir.

Beyaz kutu testi yaklaşımı alıyorsanız, genel yöntemlerinizin etrafında birim testleri oluştururken özel yöntemlerinizin uygulama ayrıntılarını göz önünde bulundurmalısınız. Kara kutu yaklaşımı uyguluyorsanız, genel veya özel yöntemlerde herhangi bir uygulama ayrıntısına karşı değil, beklenen davranışa karşı test yapmalısınız.

Şahsen, birim testlere beyaz kutu yaklaşımını tercih ediyorum. Yöntemleri ve sınıfları test edip, genel ve özel yöntemlerimde ilginç davranışlara neden olan farklı durumlara koymak için testler yapabilir ve sonuçların beklediğim gibi olduğunu iddia edebilirim.

Özel yöntemlerinizle alay etmeyin. Sağladığınız işlevselliği iyi bir şekilde kapsamak için neleri test etmeniz gerektiğini anlamak için kullanın. Bu, özellikle birim test seviyesinde geçerlidir.


1
"özel yöntemlerinizi alay etmeyin" evet, test anlayabiliyorum, onları alay ederken sen ince ince çizgiyi çılgınca geçti olabilir
Ewan

Evet ama dediğim gibi, beyaz kutu testiyle ilgili sorunum, genel ve özel yöntemler için tüm bağımlılıkları alay etmenin gerçekten büyük test yöntemleri yaratması. Bunun nasıl ele alınacağına dair bir fikrin var mı?
Fran Sevillano

8
@FranSevillano Eğer bu kadar çok stub veya alay etmek zorunda kalırsanız, genel tasarımınıza bakarım. Bir şey hissediyor.
Thomas Owens

Bir kod kapsamı aracı bu konuda yardımcı olur.
Andy

5
@FranSevillano: Bir şeyin tonlarca bağımlılığa sahip olması için bir sınıfın pek çok iyi nedeni yok. Tonlarca bağımlılığınız varsa, muhtemelen bir Tanrı sınıfınız vardır.
Mooing Duck

4

Bence bu çok kötü bir fikir.

Özel üyelerin birim testleri oluşturmadaki sorun, ürün yaşam döngüsüne zayıf uymasıdır.

Bu yöntemleri özel yapmak için SEÇMENizin nedeni, sınıflarınızın yapmaya çalıştıkları şeyin merkezinde olmamalarıdır; yalnızca şu anda bu işlevi nasıl uyguladığınıza yardımcı olan yardımcılardır. Refactor olarak, bu özel detaylar muhtemelen aday olacak ve yeniden düzenleme ile sürtünmeye neden olacak.

Ayrıca, genel ve özel üyeler arasındaki önemli bir fark, genel API'nizi dikkatlice düşünmeniz ve iyi bir şekilde belgelemeniz ve iyi kontrol etmenizdir (iddialar vb.). Ancak özel bir API ile dikkatlice düşünmek anlamsız olacaktır (kullanımı çok yerelleştirildiğinden boşa harcanan bir çaba). Özel yöntemlerin birim testlere sokulması, bu yöntemlere dış bağımlılıklar yaratma anlamına gelir. Yani API'nin kararlı ve iyi belgelenmiş olması gerekir (çünkü biri bu birim testlerinin neden / ne zaman başarısız olduğunu anlamalıdır).

Size öneririm:

  • Bu yöntemlerin özel olup olmayacağını RETHINK
  • Bir kerelik testler yazın (sadece doğru olduğundan emin olmak için testi geçici olarak herkese açık hale getirin, böylece testi test edip silebilirsiniz)
  • #İfdef ve iddiaları kullanarak uygulamanıza koşullu test oluşturdu (testler yalnızca hata ayıklama yapılarında yapılır).

Bu işlevselliği test etme eğiliminiz ve mevcut herkese açık API'nız aracılığıyla test edilmesinin zor olduğunu takdir edin. Ancak kişisel olarak modülerliğe test kapsamından daha fazla değer veriyorum.


6
Katılmıyorum. IMO, entegrasyon testleri için% 100 doğrudur. Ancak birim testlerle işler farklıdır; Birim testinin amacı, bir hatanın nerede olduğunu tam olarak saptamaktır, böylece hızlı bir şekilde düzeltebilirsiniz. Kendimi bu durumda sık sık buluyorum: çok az kamu yöntemim var çünkü bu gerçekten benim sınıflarımın temel değeri (dediğin gibi). Ancak, ne kamu ne de özel 400 hat yöntemleri yazmaktan kaçının. Bu yüzden birkaç kamu yöntemim ancak onlarca özel yöntem yardımıyla hedeflerine ulaşabilir. Bu "hızlı bir şekilde düzeltmek" için çok fazla kod. Hata ayıklayıcıyı vb.
Başlatmalıyım

6
@marstato: öneri: önce testler yazmaya başlayın ve unittests hakkındaki fikrinizi değiştirin: hataları bulamazlar, ancak kodun geliştiricinin amaçladığı gibi çalıştığını doğrulayın.
Timothy Truckle

@marstato Teşekkürler! Evet. Testler her zaman ilk kez geçer, bir şeyleri kontrol ettiğinizde (ya da kontrol edemezdiniz!). Kodu geliştirdikçe, bir şeyi kırdığınızda size bir başlık verir ve İYİ regresyon testleriniz varsa, sorunların nereye bakılacağı konusunda size KONFOR / REHBERLİK verir (kararlı olan şeylerde değil) ve iyi regresyon testi).
Lewis Pringle

@marstato "Birim testinin amacı bir hatanın nerede olduğunu bulmaktır" - Bu OP'nin sorusuna yol açan yanlış anlamadır. Birim testinin amacı, bir API'nin amaçlanan (ve tercihen belgelenmiş) davranışını doğrulamaktır.
StackOverthrow

4
@marstato "Entegrasyon testi" adı, birden fazla bileşenin birlikte çalıştığı (yani düzgün bir şekilde entegre oldukları) testlerinden gelir. Birim testi, tek bir bileşenin tek başına yapması gereken şeyi tek başına test ediyor, bu da temel API'sinin belgelendiği / gerektiği gibi çalıştığı anlamına geliyor. Bu terimlerin hiçbiri , entegrasyonun çalışmasını veya tek birimin çalışmasını sağlamanın bir parçası olarak dahili uygulama mantığı testlerini dahil edip etmediğiniz hakkında hiçbir şey söylemez .
Ben

3

UnitTests kod yerine genel gözlemlenebilir davranışı test eder , burada "public" şu anlama gelir: dönüş değerleri ve bağımlılıklarla iletişim.

"Birim", aynı sorunu çözen herhangi bir koddur (veya daha kesin olarak: değiştirmek için aynı nedene sahiptir). Bu tek bir yöntem veya bir grup sınıf olabilir.

Test etmek istememenizin temel nedeni private methods: uygulama ayrıntılarıdır ve yeniden düzenleme sırasında bunları değiştirmek isteyebilirsiniz (işlevselliği değiştirmeden OO ilkelerini uygulayarak kodunuzu geliştirin). Bu, tam olarak birim testlerinizin değişmesini istemediğinizde, CuT'unuzun davranışının yeniden düzenleme sırasında değişmediğini garanti edebilmeleri içindir.

Ancak, ben sadece bir kamuoyu arayüzlerini test edebilmek için bir gazilyon dersi almak istemiyorum ve birçok ders için sadece kamusal yöntemleri test edersem çok bağımlılıklarla alay etmek zorunda kaldığımı ve birim testlerinin muazzam ve takip edilmesi zor.

Genellikle tam tersini deneyimliyorum: Sınıflar ne kadar küçükse (daha az sorumlulukları varsa) sahip oldukları bağımlılıklar o kadar azdır ve hem yazma hem de okuma için birim testler o kadar kolay olur.

İdeal olarak sınıflarınıza aynı seviyede soyutlama modeli uygularsınız . Bu, sınıflarınızın ya bir iş mantığı (tercihen yalnızca kendi durumunu koruyarak kendi parametreleri üzerinde çalışan "saf işlevler") (x) ya da diğer nesneler üzerinde aynı anda değil, çağrı yöntemleri sağladıkları anlamına gelir .

Bu şekilde iş davranışını birim olarak test etmek çocuk oyuncağıdır ve "temsilci seçme" nesneleri genellikle başarısız olmak için çok basittir (dallanma yok, durum değişikliği yok), böylece birim testlere gerek kalmaz ve testleri entegrasyona veya modül testlerine bırakılabilir


1

Kod üzerinde çalışan tek programcı olduğunuzda, özellikle uygulama çok büyük veya çok karmaşıksa, birim testinin bir değeri vardır. Birim sınamanın önemli olduğu yerler, aynı kod tabanında çalışan çok sayıda programcıya sahip olduğunuz zamandır. Bu daha büyük ekiplerde çalışmanın bazı zorluklarına yönelik olarak birim testi kavramı tanıtıldı.

Birim testlerinin daha büyük ekiplere yardımcı olmasının nedeni tamamen sözleşmelerle ilgilidir. Kodum başkası tarafından yazılan koda çağrı yapıyorsa, diğer kişinin kodunun çeşitli durumlarda ne yapacağına dair varsayımlar yapıyorum. Bu varsayımların hala doğru olması şartıyla, kodum yine de çalışır, ancak geçerli olan varsayımları ve bu varsayımların ne zaman değiştiğini nasıl bilebilirim?

Burada birim testleri devreye girer. Bir sınıfın yazarı, sınıflarının beklenen davranışlarını belgelemek için birim testleri oluşturur. Birim testi, sınıfı kullanmanın tüm geçerli yollarını tanımlar ve birim testini çalıştırmak bu kullanım durumlarının beklendiği gibi çalıştığını doğrular. Sınıfınızdan yararlanmak isteyen başka bir programcı, sınıfınız için bekleyebilecekleri davranışı anlamak için birim testlerinizi okuyabilir ve bunu sınıfınızın nasıl çalıştığı ile ilgili varsayımları için bir temel olarak kullanabilir.

Bu şekilde, sınıfın genel yöntem imzaları ve birim testleri birlikte, sınıf yazarı ile kodunda bu sınıfı kullanan diğer programcılar arasında bir sözleşme oluşturur.

Bu senaryoda, özel yöntemlerin sınanmasını dahil ederseniz ne olur? Açıkçası bu hiç mantıklı değil.

Kodunuz üzerinde çalışan tek programcıysanız ve kodunuzu hata ayıklamanın bir yolu olarak birim testini kullanmak istiyorsanız, o zaman herhangi bir zarar görmüyorum, bu sadece bir araç ve bunun için çalışan herhangi bir şekilde kullanabilirsiniz ancak birim testin başlatılmasının nedeni bu değildi ve birim testin en önemli faydalarını sağlamaz.


Ben bununla mücadele ediyorum, çünkü bağımlılıkları değiştiririm, eğer herhangi bir bağımlılık davranışını değiştirirse, testim başarısız olmaz. Bu hatanın ünite testinde değil bir entegrasyon testinde meydana gelmesi bekleniyor mu?
Todd

Alaycı gerçek uygulama ile aynı şekilde davranmalıdır, ancak bağımlılıkları yoktur. Gerçek uygulama şimdi farklı olacak şekilde değişirse, bu bir entegrasyon testi hatası olarak görünür. Şahsen alayların ve gerçek uygulamaların geliştirilmesinin tek bir görev olduğunu düşünüyorum. Yazma birimi testleri kapsamında alay yapmıyorum. Bu şekilde, sınıflarımın davranışını değiştirdiğimde ve uyuşacak şekilde değiştirdiğimde, birim testlerini çalıştırmak bu değişiklikle kırılan diğer tüm sınıfları tanımlayacaktır.
bikeman868

1

Böyle bir soruyu cevaplamadan önce, gerçekte neyi başarmak istediğinize karar vermeniz gerekir.

Kod yazıyorsunuz. Umarım sözleşmesini yerine getirir (başka bir deyişle, yapması gerekeni yapar. Yapması gerekeni yazmak, bazı insanlar için dev bir adımdır).

Kodun yapması gerekeni yaptığını makul bir şekilde ikna etmek için, ya ona yeterince uzun bakıyorsunuz ya da sizi "kod tüm bu testleri geçerse doğru" diye ikna etmek için yeterli vakayı test eden test kodu yazıyorsunuz.

Genellikle sadece bazı kodların genel olarak tanımlanmış arayüzüyle ilgilenirsiniz. Ben senin kütüphane kullanırsam, yalnızca bu, bunu düzgün çalışması yapılmış nasıl umurumda değil does düzgün çalışması. Birim testleri yaparak kütüphanenizin doğru olduğunu onaylıyorum.

Fakat kütüphaneyi yaratıyorsunuz. Düzgün çalışmasını sağlamak zor olabilir. Diyelim ki sadece kütüphanenin X işlemini doğru bir şekilde yapmasını önemsiyorum, bu yüzden X için bir birim testim var. Kütüphaneyi oluşturmaktan sorumlu geliştirici olan, her biri tamamen önemsiz olan A, B ve C adımlarını birleştirerek X'i uygulayın. Kütüphanenizin çalışmasını sağlamak için A, B ve C'nin her birinin doğru çalıştığını doğrulamak için testler eklersiniz. Bu testleri istiyorsunuz. "Özel yöntemler için birim testler yapmamalısınız" demek oldukça anlamsızdır. Sen bu özel yöntemler için testler istiyoruz. Belki birisi size özel yöntemleri test eden birimin yanlış olduğunu söyler. Ancak bu sadece onlara “birim testleri” değil “özel testler” ya da ne derseniz deyin demektir.

Swift dili, işlevlere "test edilebilir" özelliği vererek test etmek istediğiniz için A, B, C'yi genel yöntemler olarak göstermek istemediğiniz sorunu çözer. Derleyici, birim testlerinden özel test edilebilir yöntemlerin çağrılmasına izin verir, ancak test dışı koddan çağrılamaz.


0

Evet, delisin .... BİR FOX GİBİ!

Bazıları dile bağlı olan özel yöntemleri test etmenin birkaç yolu vardır.

  • yansıması! kurallar çiğnenmek içindir!
  • onları koruma altına al, devral ve geçersiz kıl
  • friend / InternalsVisibleTo sınıfları

Genel olarak, özel yöntemleri test etmek istiyorsanız, muhtemelen bunları bir bağımlılık üzerinde genel yöntemlere taşımak ve bunu test etmek / enjekte etmek istersiniz.


Bilmiyorum, gözlerimde bunun iyi bir fikir olmadığını açıkladın ama soruyu cevaplamaya devam ettin
Liath

Tüm üsleri kapadığımı sanıyordum :(
Ewan

3
Ben iptal ettim, çünkü özel yardımcı yöntemlerinizi sadece onları test etmek için genel API'ya gösterme fikri çılgın ve her zaman bunu düşündüm.
Robert Harvey

0

Pragmatik olun. Özel durumlardaki özel durumlarda, örneğin durumunu ve parametreleri genel bir yönteme göre bu tür durumlar olacak şekilde ayarlayarak test etmek, genellikle çok karmaşıktır.

Bu "özel" yöntemleri test etmek için açıkça adlandırılmış bir ekstra internalerişimci ( InternalsVisibleTotest derlemesi bayrağıyla birlikte) ekliyorum DoSomethingForTesting(parameters).

Elbette, uygulama bir şekilde değişebilir ve test erişimcilerini içeren testler geçersiz hale gelir. Bu hala test edilmemiş vakalardan veya okunamayan testlerden daha iyidir.

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.