Bazen özel işlevler basitçe henüz çıkarılmamış iç işlev birimleridir. Öyleyse neden onları test etmiyorsun?


9

Bazen bir modülün veya sınıfın özel işlevleri, kendi testlerini hak edebilecek, henüz çıkarılmamış iç işlev birimleridir. Öyleyse neden onları test etmiyorsun? Onlar için daha sonra çıkarılıp çıkarılmadıklarını / ne zaman alındıklarını test edeceğiz . Öyleyse neden testleri hala aynı dosyanın parçası olduklarında yazmıyorsunuz?

Göstermek:

resim açıklamasını buraya girin

İlk olarak ben yazdım module_a. Şimdi bunun için testler yazmak istiyorum. 'Özel' işlevini test etmek istiyorum _private_func. Neden bunun için bir test yazamayacağımı anlamıyorum, daha sonra yine de kendi dahili modülüne yeniden bakabilir ve daha sonra bunun için testler yazabilirim.


Aşağıdaki işlevlere sahip bir modülüm olduğunu varsayalım (ayrıca bir sınıf olabilir):

def public_func(a):
    b = _do_stuff(a)
    return _do_more_stuff(b)

_do_stuffve _do_more_stuffmodülün 'özel' işlevleridir.

Uygulama ayrıntılarını değil, yalnızca ortak arayüzü test etmemiz gerektiği fikrini anlıyorum. Ancak, işte şey:

_do_stuffve _do_more_stuffmodülün işlevselliğinin çoğunu içerir. Her biri farklı bir 'dahili' modülün ortak bir işlevi olabilir. Ancak bunlar henüz gelişmemiş ve ayrı dosyalara çıkarılacak kadar büyük değil.

Bu nedenle, bu işlevlerin test edilmesi doğru hissettiriyor çünkü önemli işlevsellik birimleri. Kamusal işlevler olarak farklı modüllerde olsaydı, onları test ederdik. Öyleyse neden farklı bir dosyaya henüz (veya hiç) aktarılmadığında bunları test etmiyorsunuz?


2
TDD'de Yeni'nin
gnat

2
"Özel yöntemler birim testi için faydalıdır ..." "... özel yöntemle çalışmak bana birim testlerinde yararlı ve güvenilir bir iyileştirme getirir. Aksine," test edilebilirlik için "erişim sınırlamalarını zayıflatmak bana sadece anlaşılır, anlaşılması zor bir şey verir Ayrıca küçük bir yeniden düzenleme tarafından kırılma riski altında olan test kodunun bir parçası; Açıkçası aldığım şüpheli teknik borç gibi görünüyor "
gnat

3
"Özel fonksiyonları test etmeli miyim?" Hayır. Asla, asla, asla.
David Arno

2
@DavidArno Neden? Dahili testlerin alternatifi nedir? Sadece entegrasyon testleri? Yoksa daha fazla şeyi herkese açık hale getirmek mi? (deneyimlerime göre, çoğunlukla özel yöntemler değil, iç sınıflarda genel yöntemleri test ediyorum)
CodesInChaos

1
Bunun için testler yazmaya ihtiyaç duyulması yeterince önemliyse, zaten ayrı bir modülde olmalıdır. Değilse, genel API'yı kullanarak davranışını test edersiniz.
Vincent Savard

Yanıtlar:


14

Test etme ihtiyacı halka açık olma ihtiyacı ile aynı şey değildir.

Önemsiz kod, maruziyetten bağımsız olarak teste ihtiyaç duyar. Test edilmesine rağmen halka açık olmayan davranışların var olmasına gerek yoktur.

Bu çelişkili görünümler, her işlevi herkese açık hale getirmenize veya herkese açık olmadıkça kodu bir işleve dahil etmeyi reddetmenize neden olabilir.

Cevap bu değil. Özel yardımcı fonksiyonlar yaratmaya istekli olun. Bunları mümkün olduğunca kullanan genel arayüz aracılığıyla test edin.

Ortak arabirim üzerinden test yapmak özel işlevi yeterince kullanmazsa özel işlev çok fazla izin vermeye çalışır.

Doğrulama, özel işlevin izin verdiği şeyi daraltmaya yardımcı olabilir. Ortak arabirimden geçen bir boş değeri geçemezseniz, yine de bir tane gelirse bir istisna atabilirsiniz.

Neden ki? Neden hiç görmeyeceğinizi test edin? Çünkü işler değişir. Şimdi özel olabilir ancak daha sonra herkese açık olabilir. Arama kodu değişebilir. Null değerini açıkça reddeden kod, doğru kullanımı ve beklenen durumu netleştirir.

Elbette null iyi olabilir. Bu sadece bir örnek. Ancak bir şey bekliyorsanız, bu beklentiyi netleştirin.

Bu, aklınızdan geçirdiğiniz türden bir test olmayabilir ancak umarım uygun olduğunda özel yardımcı işlevler oluşturmak isteyeceksinizdir.

Test etme isteği iyidir, ancak herkese açık API'nızın tasarımında itici güç olmamalıdır. Genel API'yı kullanımı kolay olacak şekilde tasarlayın. Her işlevin herkese açık olması büyük olasılıkla olmayacaktır. API, insanların koda dalış yapmadan nasıl kullanabileceklerini anlayabilecekleri bir şey olmalıdır. Bu tür insanları bu garip yardımcı fonksiyonun ne için olduğunu merak etmeyin.

Dahili bir modülde genel yardımcı işlevlerini gizlemek, yardımcıları test için açığa çıkarırken temiz bir API ihtiyacına saygı gösterme girişimidir. Bunun yanlış olduğunu söylemeyeceğim. Farklı bir mimari katmana doğru ilk adımı atıyor olabilirsiniz. Ama lütfen, özel yardımcı işlevleri ilk önce kullanan genel işlevler aracılığıyla test etme sanatında ustalaşın. Bu şekilde, bu geçici çözümü fazla kullanmayacaksınız.


Bir yaklaşım buldum, fikrinizi duymak isterim: özel bir işlevi test etmek istediğim bir durumda olduğumda, bunu kamu işlevlerinden biri aracılığıyla yeterince test edip edemeyeceğimi kontrol edeceğim. (tüm kenar kutuları vb. dahil). Yapabilirsem, bu işlev için özel olarak bir test yazmayacağım, ancak sadece onu kullanan genel işlevleri test ederek test edeceğim. Ancak, işlevin genel arabirim üzerinden yeterince test edilemediğini ve kendi testini hak ettiğini düşünüyorsanız, onu halkın bulunduğu bir iç modüle çıkaracağım ve bunun için testler yazacağım. Ne düşünüyorsun?
Aviv Cohn

Aynı şeyi burada yanıtlayan diğer adamlara da sorduğumu söyleyeceğim :) Herkesin fikrini duymak isterim.
Aviv Cohn

Yine, sana hayır demeyeceğim. Bunun kullanılabilirliği nasıl etkilediğine göz atma konusunda hiçbir şey söylemediğinizden endişe ediyorum. Kamu ve özel sektör arasındaki fark yapısal değildir. Kullanımı. Kamu ve özel arasındaki fark bir ön kapı ve bir arka kapı ise, etrafınızdaki çalışma arka bahçede bir kulübe inşa etmektir. İnce. İnsanlar orada kaybolmadıkları sürece.
candied_orange

1
"Ortak arabirim üzerinden test etme özel işlevi yeterince kullanmıyorsa, özel işlev çok fazla izin vermeye çalışıyor."
Kris Welsh

7

Kısa cevap: Hayır

Daha uzun cevap: Evet, ancak sınıfınızın herkese açık 'API'sı aracılığıyla

Bir sınıfın özel üyelerinin fikri, kodun 'birimi' dışında görünmez olması gereken işlevselliği temsil etmesidir, ancak bu birimi tanımlamak istediğiniz kadar büyüktür. Nesneye yönelik kodda bu birim genellikle bir sınıf haline gelir.

Sınıfınızı, çeşitli özel giriş durum kombinasyonları aracılığıyla tüm özel işlevleri çağırabilecek şekilde tasarlamalısınız. Bunu yapmanın nispeten basit bir ileri yolu olmadığını görürseniz, muhtemelen tasarımınızın daha yakından ilgilenmesi gerektiğini ima eder.


Sorunun açıklanmasından sonra, bu sadece bir anlambilim meselesidir. Söz konusu kod ayrı bir bağımsız birim olarak çalışabilir ve genel kodmuş gibi test ediliyorsa, bunu bağımsız bir modüle taşımamamanın herhangi bir faydasını göremiyorum. Şu anda, sadece gelecekteki geliştiricileri (6 ay içinde kendiniz de dahil olmak üzere), görünüşte genel kodun neden başka bir modülde gizlendiğini karıştırmaya hizmet ediyor.


Merhaba, Cevabınız için teşekkürler :) Lütfen soruyu tekrar okuyun, açıklığa kavuşturmak için düzenledim.
Aviv Cohn

Bir yaklaşım buldum, fikrinizi duymak isterim: özel bir işlevi test etmek istediğim bir durumda olduğumda, bunu kamu işlevlerinden biri aracılığıyla yeterince test edip edemeyeceğimi kontrol edeceğim. (tüm kenar kutuları dahil). Yapabilirsem, bu işlev için özel olarak bir test yazmayacağım, ancak yalnızca onu kullanan genel işlevleri test ederek test edeceğim. Ancak, işlevin genel arabirim üzerinden yeterince test edilemediğini ve kendi testini hak ettiğini düşünüyorsanız, onu halkın bulunduğu bir iç modüle çıkaracağım ve bunun için testler yazacağım. Ne düşünüyorsun?
Aviv Cohn

Aynı şeyi burada yanıtlayan diğer adamlara da sorduğumu söyleyeceğim :) Herkesin fikrini duymak isterim.
Aviv Cohn

5

Özel işlevlerin tüm amacı, genel API'yi değiştirmeden, isteğe bağlı olarak değiştirilebilen gizli uygulama ayrıntıları olmasıdır. Örnek kodunuz için:

def public_func(a):
    b = _do_stuff(a)
    return _do_more_stuff(b)

Yalnızca kullanan bir dizi public_functestiniz varsa, bunu şu şekilde yeniden yazarsanız:

def public_func(a):
    b = _do_all_the_new_stuff(a)
    return _do_all_the_old_stuff(b)

belirli bir değer için geri dönüş sonucu aaynı kaldığı sürece , tüm testleriniz iyi olacaktır. Dönüş sonucu değişirse, bir şey başarısız olduğunu vurgulayan bir test başarısız olur.

Bunların hepsi iyi bir şey: statik genel API; iyi kapsüllenmiş iç işler; ve sağlam testler.

Eğer için testler yazdığım Ancak, _do_stuffveya _do_more_stuffdaha sonra yukarıdaki değişikliği yapan, artık işlevsellik değişmedi çünkü kırık bir sürü test olurdu, ama bu işlevselliği uygulanması değiştirdiği için. Bu testlerin yeni işlevlerle çalışmak için yeniden yazılması gerekir, ancak onları çalıştırdıktan sonra, bildiğiniz tek şey bu testlerin yeni işlevlerle çalıştığıdır. Orijinal testleri kaybedecektiniz ve bu nedenle davranışının public_funcdeğişip değişmediğini bilmezsiniz ve böylece testler temel olarak işe yaramaz.

Bu kötü bir şey: değişen bir API; testlere sıkıca bağlı maruz kalan iç çalışmalar; ve uygulamada değişiklik yapılır yapılmaz değişen gevrek testler.

Yani hayır, özel fonksiyonları test etmeyin. Hiç.


Merhaba David, cevabınız için teşekkürler. Lütfen sorumu tekrar okuyun, açıklığa kavuşturmak için düzenledim.
Aviv Cohn

Meh. Dahili fonksiyonları test etmede yanlış bir şey yok. Şahsen, birkaç birim testle kapatamadıkça, önemsiz olmayan bir işlev yazmıyorum, bu nedenle iç işlevler üzerinde yapılan testlerin yasaklanması, iç işlevler yazmamı, beni çok kullanışlı bir teknikten soymamı engelleyecekti. API'ler değişiklik yapabilir ve yapabilir; yaptıklarında testleri değiştirmeniz gerekir. Bir iç fonksiyonun (ve testinin) yeniden düzenlenmesi, dış fonksiyonun testlerini bozmaz; bu testleri yaptırmanın bütün mesele bu. Genel olarak kötü tavsiye.
Robert Harvey

Gerçekten tartıştığınız şey özel işlevlerin olmaması gerektiğidir.
Robert Harvey

1
@AvivCohn Testleri garanti edecek kadar büyükler, bu durumda kendi dosyalarını alacak kadar büyükler; veya ayrı ayrı test etmeniz gerekmeyecek kadar küçüktür. Peki hangisi?
Doval

3
@RobertHarvey Hayır, "büyük sınıfları gerekirse gevşek bağlı bileşenlere ayırma" argümanı yapar. Onlar iseniz gerçekten muhtemelen paket-özel görünürlük için iyi bir kullanım-durumda olacak kamu değil.
Doval
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.