Özel kod üzerinde birim testini nasıl savunabilirim?


15

Çalışma grubumda birim testini savunmaya çalışıyorum, ancak sık sık aldığım bir itiraz, yalnızca harici olarak dışa aktarılan API (sistemimizin yalnızca minimal ve kritik olmayan bir parçası olan) için ve dahili ve özel olarak kullanılmaması gerektiğidir. kod (şimdi sadece işlevsel testlere sahip).

Birim testinin tüm koda uygulanabileceğini ve uygulanabileceğini düşünürken, iş arkadaşlarımı nasıl ikna edebilirim?


3
Test etme gereksinimi duyduğunuz özel yöntemleriniz varsa, bu genellikle kodunuzun SRP'yi ihlal ettiğini gösteren bir işarettir ve orada kendi başına çıkarılıp test edilmesi için ağlayan başka bir sınıf vardır.
Paddyslacker

@Paddyslacker: Tüm kodların test edilmesi gerektiğini hissediyorum. Tek sorumluluk ilkesini izleyen bir kod biriminin neden birim testine tabi olmaması gerektiğini anlamıyorum ...
Wizard79

4
@lorenzo, benim fikrimi kaçırdın; belki çok iyi yapmadım. Bu özel yöntemleri başka bir sınıfa çıkarırsanız, artık orijinal sınıfınızdan erişilebilir olması gerekir. Yöntemler artık herkese açık olduğu için test edilmeleri gerekecek. Test edilmeleri gerektiğini ima etmiyordum, yöntemleri doğrudan test etme gereğini hissediyorsanız, muhtemelen özel olmamaları gerektiğini ima ediyordum.
Paddyslacker

@Paddyslacker: Özel yöntemleri de doğrudan test etme gereğini hissediyorum. Neden özel olmamaları gerektiğini düşünüyorsun?
Sihirbaz79

6
Özel yöntemleri test ederek soyutlamayı bozuyorsunuz. Birim testlerinde uygulama değil durumu ve / veya davranışı test ediyor olmalısınız. Örnekleriniz / senaryolarınız özel kodun sonucunun ne olduğunu doğrulayabilmelidir - bunu zor bulursanız, Paddyslacker'in söylediği gibi, SRP'yi ihlal ettiğiniz anlamına gelebilir. Ayrıca, kodunuzun ne yaptığını gerçekten temsil etmek için örneklerinizi damıtmamış olduğunuz anlamına da gelebilir.
FinnNk

Yanıtlar:


9

İş arkadaşlarınız, gerçek birim testlerini entegrasyon testleriyle karıştırıyor olabilir. Ürününüz bir API ise (veya varsa), entegrasyon testleri NUnit test senaryoları olarak programlanabilir. Bazı insanlar yanlışlıkla bunların birim testler olduğuna inanırlar.

İş arkadaşlarınızı aşağıdakilerle ikna etmeye çalışabilirsiniz (eminim bu şeyleri zaten biliyorsunuz, tek söylediğim, iş arkadaşlarınıza işaret etmek yardımcı olabilir):

  • Test kapsamı . Bu entegrasyon testlerinin gerçek test kapsamı yüzdesini ölçün. Bu, hiç test kapsamı yürütmemiş olanlar için bir gerçeklik kontrolüdür. Giriş birkaç kat uzakta olduğunda tüm mantıksal yolları kullanmak zor olduğundan, test kapsamı% 20 ile% 50 arasında bir yerde üst üste gelir. Daha fazla kapsama alanı elde etmek için iş arkadaşlarınızın gerçek, yalıtılmış birim testleri yazması gerekir.
  • Yapılandırma . Aynı yazılımı test altında dağıtın ve belki de çalışma arkadaşlarınıza testlerini farklı bir ortamda çalıştırmanın ne kadar zor olduğunu gösterebilirsiniz. Çeşitli dosyalara yollar, DB bağlantı dizeleri, uzak hizmetlerin URL'leri, vb.
  • Yürütme zamanı . Testler gerçek birim testleri değilse ve bellekte çalışamazsa, çalışması çok zaman alacaktır.

12

Dahili / özel kodda birim testlerinin kullanılmasının nedenleri, harici olarak desteklenen API'larla tam olarak aynıdır:

  • Hataların tekrarlanmasını önlerler (birim testleri regresyon test takımınızın bir parçasını oluşturur).
  • Kodun çalıştığını belgeliyorlar (yürütülebilir bir biçimde!).
  • Onlar "kod çalışır" ne demek yürütülebilir bir tanımı sağlar.
  • Kodun gerçekten de spesifikasyonlarla eşleştiğini göstermek için otomatik bir yol sağlarlar (yukarıdaki nokta ile tanımlandığı gibi).
  • Ünitenin / sınıfın / modülün / fonksiyonun / yöntemin beklenmedik bir giriş varlığında nasıl başarısız olduğunu gösterirler.
  • Yeni ekip üyeleri için mükemmel bir dokümantasyon olan ünitenin nasıl kullanılacağına dair örnekler sunarlar.

8

Kastettiğimi düşündüğüm şekilde özel demek istiyorsan, o zaman hayır - bunu birim olarak test etmemelisin. Yalnızca gözlemlenebilir davranış / durumu test eden birim olmalısınız. TDD'nin "kırmızı-yeşil-refactor" döngüsünün arkasındaki noktayı kaçırıyor olabilirsiniz (ve önce test yapmıyorsanız, aynı prensip geçerlidir). Testler yazıldıktan ve geçtikten sonra yeniden düzenleme yapılırken değişmelerini istemezsiniz. Özel işlevselliği birim testi yapmak zorunda kalırsanız, muhtemelen genel işlevsellik etrafındaki birim testlerinin hatalı olduğu anlamına gelir. Genel kodun etrafına test yazmak zor ve karmaşıksa, sınıfınız çok fazla şey yapıyor olabilir veya probleminiz açıkça tanımlanmamış.

Daha da kötüsü, zaman içinde birim testleriniz bir top ve zincir olacak ve herhangi bir değer katmadan sizi yavaşlatacaktır (örneğin, optimizasyon veya çoğaltmanın kaldırılması gibi uygulamaların değiştirilmesi, birim testler üzerinde herhangi bir etkiye sahip olmamalıdır). Bununla birlikte, dahili kod, davranış / durum gözlemlenebilir olduğundan (sadece sınırlı bir şekilde) birim test edilmelidir.

Birim testini ilk yaptığımda, özel şeyleri test etmek için her türlü hileyi çektim, ancak şimdi, kemerin altında birkaç yıl geçirdim, zaman kaybından daha kötü görüyorum.

İşte biraz aptalca örnek, elbette gerçek hayatta bunlardan daha fazla testiniz olacak:

Diyelim ki sıralı bir dize listesi döndüren bir sınıfınız var - sonucun sıralandığını kontrol etmelisiniz, aslında bu listeyi nasıl sıraladığını değil. Uygulamanızı, listeyi sıralayan tek bir algoritma ile başlatabilirsiniz. Bunu yaptıktan sonra, sıralama algoritmanızı değiştirirseniz testinizin değişmesi gerekmez. Bu noktada tek bir testiniz var (sıralamanın sınıfınıza gömülü olduğu varsayılarak):

  1. Sonucum sıralanıyor mu?

Şimdi iki algoritma istediğinizi (belki bazı durumlarda daha verimli, ancak diğerlerinde değil) istediğinizi varsa, o zaman her algoritma farklı bir sınıf tarafından sağlanabilir (ve genellikle gerekir) ve sınıfınız onlardan alır - bunun olup olmadığını kontrol edebilirsiniz. seçtiğiniz senaryoları taklit kullanarak, ancak orijinal testiniz hala geçerlidir ve yalnızca gözlemlenebilir davranışı / durumu doğruladığımız için değiştirilmesine gerek yoktur. 3 test ile sonuçlanırsınız:

  1. Sonucum sıralanıyor mu?
  2. Bir senaryo verildiğinde (diyelim ki ilk liste neredeyse başlamak üzere sıralanıyor) X algoritmasını kullanarak dizeleri sıralayan sınıfa yapılan bir çağrı mı?
  3. Verilen bir senaryo (ilk liste rastgele sıradadır) Y algoritmasını kullanarak dizeleri sıralayan sınıfa yapılan bir çağrıdır?

Alternatif, sınıfınızdaki özel kodu test etmeye başlamak olurdu - bundan hiçbir şey kazanmıyorsunuz - yukarıdaki testler, birim testleri söz konusu olduğunda bilmem gereken her şeyi anlatıyor. Özel testler ekleyerek kendinize düz bir ceket inşa edersiniz, sadece sonucun sıralandığını değil, aynı zamanda nasıl sıralandığını da kontrol etseydiniz ne kadar daha fazla iş olurdu?

Testler (bu türden) yalnızca davranış değiştiğinde değişmeli, özel koda karşı testler yazmaya başlamalı ve bu pencereden dışarı çıkmalıdır.


1
Belki de "özel" anlamında bir yanlış anlama vardır. Sistemimizde kodun% 99'u "özel" dir, o zaman sistemin bileşenlerinden birini otomatikleştirmek / uzaktan kontrol etmek için küçük bir API'miz vardır. Yani tüm diğer modüllerin kodlarını test eden birim.
Sihirbaz79

4

İşte başka bir neden: Varsayımsal durumda harici API'yi özel parçalara karşı test eden birim arasında seçim yapmak zorunda kalacağım, özel parçaları seçerdim.

Her özel bölüm bir test tarafından kapsanıyorsa, bu özel bölümlerden oluşan API, yalnızca üst katman hariç olmak üzere, neredeyse% 100 oranında kapsanmalıdır. Ancak bunun ince bir tabaka olması muhtemeldir.

Öte yandan, sadece API'yi test ederken olası tüm kod yollarını tam olarak kapsamak gerçekten zor olabilir.


+1 "Öte yandan ..." Ama başka bir şey yoksa, bir hatanın en çok zarar vereceği testleri ekleyin.
Tony Ennis

2

İnsanların birim testini kabul etmelerini sağlamak zordur çünkü zaman kaybı ("başka bir para kazanma projesi kodlayabiliriz!") Veya özyinelemeli ("Ve sonra test senaryoları için test senaryoları yazmalıyız!") Her ikisini de söylemekten suçluyum.

İlk kez bir hata bulduğunuzda, mükemmel olmadığınız gerçeğiyle (programcıların ne kadar çabuk unuttuğumuzu!) Ve "Hmmm."


Birim testinin diğer bir yönü, testin test edilebilir olması için yazılması gerektiğidir. Bazı Kodların kolayca test edilebilir ve Bazı Kodların olmadığını anlamak iyi bir programcının "Hmmm" olmasını sağlar.


İş arkadaşınıza birim testinin neden yalnızca dışa dönük API'lar için yararlı olduğunu sordunuz mu?


Birim testinin değerini göstermenin bir yolu, kötü bir hatanın olmasını beklemek ve daha sonra birim testinin bunu nasıl önleyebileceğini göstermektir. Bu, yüzlerine sürtmek değil, akıllarında, birim testini bir Fildişi Kulesi Teorikinden siper içi gerçekliğe taşımak.

Başka bir yol, aynı hatanın iki kez gerçekleşmesini beklemektir . "Uhhh, iyi Boss, geçen haftaki sorundan sonra null değerini test etmek için kod ekledik, ancak kullanıcı bu sefer boş bir şey girdi!"


Örnek olun. SİZİN kodunuz için birim testleri yazın, ardından patronunuza değeri gösterin. Sonra patronun bir gün öğle yemeği için pizza arayacağını ve bir sunum yapıp yapmayacağını görün.


Son olarak, prod itmek üzereyken hissettiğim rahatlığı söyleyemem ve birim testlerinden yeşil bir çubuk alıyorum.


2

Ve özel kod (kamu kodu (ya ...) tarafından çağrılır özel kod tarafından çağrılan veya özel kod) Kamu kod tarafından çağrılan özel kod: Özel kodun iki türü vardır etmez neticede halk tarafından çağrılmadığı kodu.

Birincisi, genel kod testleriyle zaten test ediliyor. Çağrılamaz ikincisi teneke hiç ve böylece test değil silinmelidir.

TDD yaptığınızda, denenmemiş özel kodun mevcut olmasının imkansız olduğunu unutmayın.


Sistemimizde, kodun% 99'u üçüncü türdür : özel, genel kod tarafından çağrılmaz ve sistem için gereklidir (sistemimizin yalnızca küçük bir kısmı harici, genel API'ye sahiptir).
Sihirbaz79

1
"TDD yaptığınızda denenmemiş özel kodun mevcut olmasının imkansız olduğunu unutmayın." <- testin belirli bir dalı kapsamak için tek test olduğunu bilmeden bir test senaryosunu silin. Tamam, bu daha "şu anda denenmemiş" bir kod, ama daha sonra önemsiz bir yeniden düzenleme bu kodu değiştirmek görmek için yeterince kolaydır ... sadece test paketi artık kapsamaz.
Frank Shearar

2

Birim testi, kodunuzun test birimleri ile ilgilidir. Birimin ne olduğunu tanımlamak size kalmıştır. İş arkadaşlarınız birimleri API öğeleri olarak tanımlar.

Her neyse, test API'sı da özel kod kullanılmasına neden olmalıdır. Kod kapsamını, birim test ilerlemesinin bir göstergesi olarak tanımlarsanız, tüm kodunuzu test etmeniz gerekir. Kodun bir kısmına ulaşılmadıysa, iş arkadaşlarınıza üç seçenek verin:

  • o parçayı kapatmak için başka bir test senaryosu tanımlamak
  • ünite testi bağlamında neden kapsanamayacağını, ancak diğer durumlarda kapsanması gerektiğini doğrulamak için kodu analiz edin,
  • haklı olmayan, kapsanmayan ölü kodları kaldırın.

Sistemimizde API, üçüncü taraf bir uygulama için otomasyon / uzaktan kumandaya izin veren minimum bir parçadır. Yalnızca% 1 kod kapsamı için API hesaplarını test etme ...
Sihirbaz79
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.