Ünite testlerini gereksinime veya yönteme göre bölme


17

Birim testleri yazmak istediğim bir yöntem var. Metodun uygulanmasını tartışmak istemediğim için oldukça genel tutacağım, sadece test etmek. Yöntem:

public void HandleItem(item a)
{         
     CreateNewItem();
     UpdateStatusOnPreviousItem();
     SetNextRunDate();
}

Bu sınıfın, daha sonra mantığı gerçekleştirmek için bazı özel yöntemleri çağıran bir genel yöntemi vardır.

Bu yüzden birim testini yazarken her üç şeyin de yapıldığını kontrol etmek istiyorum. Hepsi aynı koşuda çağrıldığından, bir test olarak yapabileceğimi düşündüm:

public void GivenItem_WhenRun_Thenxxxxx
{
     HandleItem(item);
     // Assert item has been created
     // Assert status has been set on the previous item
     // Assert run date has been set
}

Ama üç ayrı test olarak da yazabileceğimi düşündüm:

public void GivenItem_WhenRun_ThenItemIsCreated()
{
    HandleItem(item);
}

public void GivenItem_WhenRun_ThenStatusIsUpdatedOnPreviousItem()
{
   HandleItem(item);
}

public void GivenItem_WhenRun_ThenRunDateIsSet()
{
     HandleItem(item);
}

Bu yüzden benim için bu aslında gereksinimleri listelemek gibi daha güzel görünüyor, ancak daha sonra üçü de ilgili ve test edilen yöntemde yapılanla aynı işi gerektiriyor, bu yüzden aynı kodu 3 kez çalıştırıyorum.

Bununla ilgili önerilen bir yaklaşım var mı?

Teşekkürler

Yanıtlar:


30

Her iki yaklaşım arasında ince bir fark vardır. İlk durumda, ilk Assertbaşarısız olduğunda, diğer ikisi artık çalıştırılmaz. İkinci durumda, biri başarısız olsa bile her üç test de her zaman yapılır. Test edilen işlevin niteliğine bağlı olarak, bu durum sizin durumunuza uygun olabilir veya olmayabilir:

  • eğer üç varsayımı diğerinden bağımsız olarak çalıştırmak mantıklıysa, biri başarısız olduğunda, diğer ikisi hala başarısız olmayabilir, o zaman ikinci yaklaşım, bir çalışmada tüm 3 test için tam test sonuçlarını elde etmenizi sağlar. Bu, bir sonraki derleme yapmadan önce bir kerede 3 hatayı düzeltme şansı verdiğinden, dikkate değer derleme süreleriniz varsa yararlı olabilir.

  • Bununla birlikte, ilk testin başarısız olması her zaman diğer iki testin de başarısız olacağını ima ederse, muhtemelen ilk yaklaşımı kullanmak daha iyidir (çünkü önceden biliyorsanız, bir testi çalıştırmak çok mantıklı değildir. başarısız).


2
+1, iyi bir nokta. İnşa sürelerinin de bir darboğaz olabileceği aklıma gelmedi .
Kilian Foth

1
@KilianFoth: C ++ 'da yeterince sık çalışmıyorsunuz :(
Matthieu M.

1
@MatthieuM .: adil olmak için soru "C #" olarak etiketlendi
Doc Brown

10

Kısa cevap: Çok daha önemli olduğunu Testlerinizi daha tüm işlevselliği kapsayacak nasıl yaptıklarını.

Daha uzun cevap: Hala bu büyük ölçüde eşdeğer çözümler arasından seçim yapmak istiyorsanız, en iyisi için yardımcı ölçütler kullanabilirsiniz. Örneğin,

  • okunabilirlik: yöntem yakından ilişkili olmayan birçok şey yaparsa, birleşik bir testin anlaşılması zor olabilir. Bununla birlikte, yöntemin kendisini anlamak zor olabilir, bu yüzden belki de test yerine yöntemi yeniden düzenlemelisiniz!)
  • verimlilik: yöntemin uygulanması uzun zaman alıyorsa, zaman kazanmak için üç kontrolün tümünü birleştirmenin zayıf bir nedeni olabilir
  • verimlilik2: çerçevenizin kurulum kodunu çalıştırmak uzun zaman alıyorsa, birden fazla test yönteminden kaçınmanın zayıf bir nedeni de olabilir. (Ancak, bu gerçekten bir sorunsa, muhtemelen test kurulumunuzu düzeltmeli veya değiştirmelidir - regresyon testleri, yıldırım hızında çalıştıramazsanız değerlerinin çoğunu kaybeder.)

3

Birden fazla onaylı bir yöntem çağrısı kullanın. İşte nedeni:

HandleItem (a) 'yı test ettiğinizde, yöntemin öğeyi doğru duruma getirdiğini test edersiniz. "Test başına bir onaylama" yerine "test başına bir mantıksal kavram" düşünün.

Soru: Bir CreateNewItem başarısız, ancak diğer iki yöntem başarılı olursa, bu HandleItem başarıyla tamamlandığı anlamına mı geliyor? Tahmin etmiyorum.

Birden fazla bildirimde (uygun mesajlarla) neyin başarısız olduğunu tam olarak bilirsiniz. Bir yöntemi birden çok girişten kaçınmak için değil, genellikle birden çok giriş veya giriş durumu için birden çok kez test edersiniz.

IMO, bu sorular genellikle başka bir şeyin işaretidir. Bu, HandleItem'in gerçekten sadece "yöntem testi" yapabileceğiniz bir şey olmadığının bir işaretidir, çünkü sadece diğer yöntemlere delege gibi görünüyor. HandleItem'in diğer yöntemleri doğru şekilde çağırdığını doğruladığınızda, daha çok bir entegrasyon testi adayı olur (bu durumda hala 3 öneriniz olur).

Diğer 3 yöntemi herkese açık hale getirmeyi ve bağımsız olarak test etmeyi düşünebilirsiniz. Ya da başka bir sınıfa bile çekiyorlar.


0

2. yaklaşımı kullanın. 1. yaklaşımınızla, test başarısız olursa nedenini hemen bilemezsiniz, çünkü başarısız olan 3 işlevden biri olabilir. İkinci yaklaşımla sorunun nereden kaynaklandığını hemen anlayacaksınız. Test Kurulumu işlevinizin içine yinelenen kod koyabilirsiniz.


-1

IMHO, bu yöntemin üç bölümünü ayrı ayrı test etmelisiniz, böylece kodunuzun aynı kısmını iki kez geçmekten kaçınırken, işlerin ne zaman yanlış gittiğini daha spesifik olarak biliyorsunuz.


-2

Kullanım durumunuz için ayrı test yöntemleri yazmak için güçlü bir durum olduğunu düşünmüyorum. Her üç değişken koşuldan da sonuç almak istiyorsanız, üçünü de test edebilir ve hatalarını a ile birleştirerek stringve testi tamamladıktan sonra dizenin hala boş olup olmadığını söyleyerek yazdırabilirsiniz . Hepsini aynı yöntemde tutarak, koşullarınız ve hata iletileriniz, yöntemin beklenen post-koşulunu, daha sonra ayrılabilecek üç yönteme bölmek yerine, tek bir yerde belgelemektedir.

Bu, tek testinizin daha fazla koda sahip olacağı anlamına gelir, ancak bu bir sorun olan çok sayıda post-koşulunuz varsa, muhtemelen içindeki yöntemleri tek tek test etmek için test yöntemlerinizi yeniden düzenlemek istersiniz HandleItem.

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.