Tek bir birim testinde birden fazla değerlendirme yapılması uygun mudur?


397

Yorumlaması olarak bu büyük yazı Roy Osherove söz OAPT tek testteki her bir sav ileri çalışacak şekilde tasarlanmıştır projeyi.

Aşağıdakiler projenin ana sayfasına yazılmıştır:

Doğru birim testleri tam olarak bir nedenden ötürü başarısız olmalıdır, bu nedenle birim test başına bir onay kullanmanız gerekir.

Ve ayrıca, Roy yorumlarda yazdı:

Kılavuzum genellikle test başına bir mantıksal KONSEP testi yapmanızdır. Aynı nesne üzerinde birden fazla öğe olabilir . genellikle test edilenler aynı konsept olacaktır.

Bence, çok sayıda iddianın gerekli olduğu bazı durumlar var (ör. Bekçi Beyanı ), ama genel olarak bundan kaçınmaya çalışıyorum. Senin görüşün nedir? Lütfen gerçekten çok sayıda varlığın gerekli olduğu gerçek bir dünya örneği sunun .


2
Birden fazla iddia olmadan nasıl alay ediyorsun? Sahte her beklenti, sizin empoze ettiğiniz herhangi bir arama sırasını da içeren kendi başına bir iddiadır.
Christopher Creutzig, 15.03.2013

15
Geçmişte kötüye kullanılan tek bir felsefe felsefesi gördüm. Eski bir iş arkadaşı bunu mümkün kılmak için korkak bir kalıtım mekanizması kullandı. Bir çok alt sınıfa (dal başına bir) ve sadece farklı sonuçları kontrol etmek için aynı kurulum / yıkma işlemini yapan birçok teste yol açtı. Yavaş, okunması zor ve ciddi bir bakım problemiydi. Daha klasik bir yaklaşıma geri dönmesi için onu asla ikna etmedim. Gerard Meszaros'un kitabı bu konuyla ilgili ayrıntılı olarak konuşuyor.
Travis Parks

3
Genel bir kural olarak, test başına tahmin sayısını en aza indirmeye çalışmalısınız. Ancak, test sorunu kodda belirli bir yere yeterince daralttığı sürece, yararlı bir testtir.
ConditionRacer

2
Çeşitli kenar durum davranışlarını test etmek için RowTest(MbUnit) / TestCase(NUnit) yerine birden çok assentin kullanıldığı durumlar gördüm . İş için uygun aletleri kullanın! (Ne yazık ki, MSTest henüz bir satır testi yeteneğine sahip görünmüyor.)
GalacticCowboy

@GalacticCowboy Sen benzer işlevler elde edebilirsiniz RowTestve TestCasekullanarak test veri kaynakları . Büyük başarı ile basit bir CSV dosyası kullanıyorum.
julealgon

Yanıtlar:


236

Bunun mutlaka kötü bir şey olduğunu düşünmüyorum, ancak testlerimizde yalnızca tek bir iddiada bulunmaya çalışmamız gerektiğini düşünüyorum . Bu, çok daha fazla test yazdığınız anlamına gelir ve testlerimiz bir seferde yalnızca bir şeyi test eder.

Bunu söylediğimde, testlerimin yarısının aslında sadece bir tane iddiası olduğunu söyleyebilirim. Testinizde yaklaşık beş veya daha fazla değerlendirme olduğunda , sadece bir kod (test?) Kokusu olur diye düşünüyorum .

Birden fazla varlığı nasıl çözersiniz?


9
Bu cevap gibi - yani tamam, ama genel durumda iyi değil (-:
Murph

5
Ehh? Neden bunu yapasın? yöntem yürütme tam olarak aynı mı?
jgauffin

197
Birim testi başına tek bir onaylama, okuyucunun yukarı ve aşağı kaydırma yeteneğini test etmek için harika bir yoldur.
Tom,

3
Bunun arkasında herhangi bir sebep var mı? Olduğu gibi, bu güncel cevap sadece ne olması gerektiğini belirtir, ancak nedenini değil.
Steven Jeuris

37
Kesinlikle katılmamak. Cevap, tek bir iddiaya sahip olmanın hiçbir avantajını listelemiyor ve bariz dezavantajı, sadece internetteki bir cevabın dediği gibi testleri kopyala-yapıştır yapmanız gerektiğidir. Bir sonucun birden fazla alanını veya tek bir işlemin birden fazla sonucunu test etmeniz gerekiyorsa, hepsini kesinlikle bağımsız iddialarda belirtmelisiniz, çünkü bunları büyük bir blob-assert içinde test etmekten çok daha faydalı bilgiler verir. İyi bir testte, bir işlemin tek bir sonucunu değil tek bir işlemi test edersiniz.
Peter,

296

Sınamalar yalnızca bir nedenden dolayı başarısız olmalıdır, ancak bu her zaman yalnızca bir Assertifade olması gerektiği anlamına gelmez . IMHO, " Düzenle, Hareket, İddialı " düzenine uymak daha önemlidir .

Önemli olan, yalnızca bir eyleminizin olması ve ardından bu eylemin sonuçlarını iddiaları kullanarak incelemektir. Ama "Düzenle, Yasa, Assert, Testin Sonu " dır . Başka bir eylem gerçekleştirerek teste devam etmeye istekliyseniz ve daha sonra daha fazla iddiada bulunduysanız, bunun yerine ayrı bir test yapın.

Aynı işlemi test etmenin bölümlerini oluşturan birden fazla assert ifadesi gördüğüm için mutluyum. Örneğin

[Test]
public void ValueIsInRange()
{
  int value = GetValueToTest();

  Assert.That(value, Is.GreaterThan(10), "value is too small");
  Assert.That(value, Is.LessThan(100), "value is too large");
} 

veya

[Test]
public void ListContainsOneValue()
{
  var list = GetListOf(1);

  Assert.That(list, Is.Not.Null, "List is null");
  Assert.That(list.Count, Is.EqualTo(1), "Should have one item in list");
  Assert.That(list[0], Is.Not.Null, "Item is null");
} 

Sen olabilir tek assert içine bu birleştirir, ama bu ısrar farklı bir şey olmalı veya zorunluluk . Bunları birleştirmekten hiçbir gelişme yoktur.

örneğin İlki olabilir olmak

Assert.IsTrue((10 < value) && (value < 100), "Value out of range"); 

Ancak bu daha iyi değil - bunun dışındaki hata mesajı daha az belirgin ve başka bir avantajı yok. İki veya üç (veya daha fazla) iddianın bir büyük boolean koşulda birleştirilmesinin okumayı zorlaştırması, değiştirmesi zorlaştırması ve neden başarısız olduğunu çözmesi daha zor olduğu başka örnekleri düşünebileceğinize eminim. Neden bunu sadece bir kural uğruna yapıyorsun?

Not : Burada yazdığım kod NUnit ile C #, ancak ilkeler diğer diller ve çerçevelerle geçerli olacak. Sözdizimi de çok benzer olabilir.


32
Önemli olan, yalnızca bir eyleminizin olması ve ardından bu eylemin sonuçlarını iddiaları kullanarak incelemektir.
Amitābha

1
Ayrıca, zamanın pahalı olması durumunda, bir Assert’in birden fazla olması da ilginç.
Rekshino

1
@Rekshino, düzenleme zaman pahalıysa, örneğin düzenleme kodunu test başlatma rutinine koyarak düzenleme kodunu paylaşabiliriz.
Shaun Luttin

2
Yani Jaco'nun cevabıyla karşılaştırırsam, "sadece bir iddia" bana daha anlamlı olan "sadece bir iddia grubu" olur.
Walfrat

2
Bu iyi bir cevap, ama tek bir kibrin daha iyi olmadığını kabul etmiyorum. Kötü assert örneği daha iyi değildir, ancak bu doğru yapıldığında tek bir assertin daha iyi olmayacağı anlamına gelmez. Pek çok kitaplık, özel varlıklara / eşleştiricilere izin verir, böylece önceden mevcut değilse bir şey oluşturulabilir. Örneğin Assert.IsBetween(10, 100, value)yazdırır Expected 8 to be between 10 and 100 olan ayrı iyi ikiden Bence belirtmektedir. Kesinlikle gerekli olmadığını iddia edebilirsiniz, ancak genellikle bir dizi oluşturmadan önce tek bir iddiaya indirmenin kolay olup olmadığını düşünmeye değer.
Thor84no

85

Birden fazla eşyanın kötü bir şey olduğunu hiç düşünmedim.

Onu her zaman yaparım:

public void ToPredicateTest()
{
    ResultField rf = new ResultField(ResultFieldType.Measurement, "name", 100);
    Predicate<ResultField> p = (new ConditionBuilder()).LessThanConst(400)
                                                       .Or()
                                                       .OpenParenthesis()
                                                       .GreaterThanConst(500)
                                                       .And()
                                                       .LessThanConst(1000)
                                                       .And().Not()
                                                       .EqualsConst(666)
                                                       .CloseParenthesis()
                                                       .ToPredicate();
    Assert.IsTrue(p(ResultField.FillResult(rf, 399)));
    Assert.IsTrue(p(ResultField.FillResult(rf, 567)));
    Assert.IsFalse(p(ResultField.FillResult(rf, 400)));
    Assert.IsFalse(p(ResultField.FillResult(rf, 666)));
    Assert.IsFalse(p(ResultField.FillResult(rf, 1001)));

    Predicate<ResultField> p2 = (new ConditionBuilder()).EqualsConst(true).ToPredicate();

    Assert.IsTrue(p2(new ResultField(ResultFieldType.Confirmation, "Is True", true)));
    Assert.IsFalse(p2(new ResultField(ResultFieldType.Confirmation, "Is False", false)));
}

Burada, karmaşık koşulların beklenen yüklemeye dönüştürülebildiğinden emin olmak için birden fazla öğe kullanıyorum.

Yalnızca bir üniteyi test ediyorum ( ToPredicateyöntem), ancak testte aklıma gelen her şeyi ele alıyorum.


46
Birden fazla öğe hata algılama nedeniyle kötü. Eğer ilk Assert.IsTrue'nuzu geçemezseniz, diğer iddialar yürütülmez ve onlardan hiçbir bilgi alamazsınız. Öte yandan 5 kıç yerine 5 test yaptırdıysanız, faydalı bir şeyler elde edebilirsiniz
Sly

6
Tüm iddialar aynı işlevi görürse, bunun hala kötü olduğunu düşünüyor musunuz? Yukarıdaki gibi, örnek koşullamaları test eder ve herhangi biri başarısız olursa, düzeltmelisiniz. Daha önce başarısız olursa, son 2 savı kaçırmanız sizin için önemli mi?
cringe

106
Sorunlarımı birer birer düzeltirim. Bu yüzden testin bir kereden fazla başarısız olması beni rahatsız etmiyor. Onları ayırırsam aynı hataları görürüm, ama hepsi bir kerede. Her şeyi bir adım adım düzeltmeyi daha kolay buluyorum. Kabul ediyorum, bu örnekte, son iki iddia muhtemelen kendi sınavlarına yeniden yerleştirilebilir.
Matt Ellen

19
- Davan NUnit ek özellik TestCase sahiptir bu yüzden, çok temsilcisidir nunit.org/?p=testCase&r=2.5
Restuta

10
google C ++ test çerçevesi ASSERT () ve EXPECT () 'e sahiptir. EXSECT () devam ederken ASSERT () başarısızlıkta durur. Testte birden fazla şeyi doğrulamak istediğinizde bu çok kullanışlıdır.
ratkok

21

Üst düzey davranışları doğrulamak için birim testini kullanırken, kesinlikle tek bir teste birden çok iddia getirdim. İşte bazı acil durum bildirim kodları için kullandığım bir test. Testten önce çalıştırılan kod, sistemi ana işlemcinin çalışması durumunda alarmın gönderildiği bir duruma getirir.

@Test
public void testAlarmSent() {
    assertAllUnitsAvailable();
    assertNewAlarmMessages(0);

    pulseMainProcessor();

    assertAllUnitsAlerting();
    assertAllNotificationsSent();
    assertAllNotificationsUnclosed();
    assertNewAlarmMessages(1);
}

Kodun beklediğim gibi davrandığından emin olmamı sağlamak için süreçte her adımda bulunması gereken koşulları temsil ediyor. Tek bir iddiada başarısız olursa, kalanların bile kaçamayacağı umrumda değil; sistemin durumu artık geçerli değil, çünkü o sonraki iddialar. Bana değerli bir şey söylemedi Eğer * assertAllUnitsAlerting()başarısız, o zaman ne çıkaracağını bilemeyiz assertAllNotificationSent()'ın başarısı VEYA başarısızlık ben önce hataya neden ne belirlenir kadar ve düzeltildi.

(* - Tamam, problemi ayıklamak için makul derecede yararlı olabilirler. Fakat testin başarısız olduğu en önemli bilgi zaten alınmış.)


Bunu yaptığınızda, bağımlı testlere sahip test çerçevelerini daha iyi kullanmanız gerekir, daha iyi olur (örn. Testng bu özelliği destekliyor)
Kemoda

8
Ben de bunun gibi testler yazıyorum, böylece kodun ne yaptığından ve durumun değiştiğinden emin olabilirsiniz, bunun bir birim testi değil de bir entegrasyon testi olduğunu düşünüyorum.
mdma

Yeniden assertAlarmStatus (int numberOfAlarmMessages); içine yeniden yansıtma hakkında görüşleriniz nelerdir?
Borjab

1
Sizin iddialarınız çok güzel test isimleri yapar.
Bjorn Tipling 21:16

Geçersiz girişte bile testin çalışmasına izin vermek daha iyidir. Size bu şekilde daha fazla bilgi verir (ve özellikle ummadığınız zamanlarda hala geçerse).
CurtainDog

8

Bir yöntemde çoklu iddiaların kötü bir şey olmadığını düşünmemin bir başka nedeni de aşağıdaki kodda tanımlanmıştır:

class Service {
    Result process();
}

class Result {
    Inner inner;
}

class Inner {
    int number;
}

service.process()Testimde, Innersınıf örneklerinde doğru sayıyı döndüren testi yapmak istiyorum .

Test etmek yerine ...

@Test
public void test() {
    Result res = service.process();
    if ( res != null && res.getInner() != null ) Assert.assertEquals( ..., res.getInner() );
}

yapıyorum

@Test
public void test() {
    Result res = service.process();
    Assert.notNull(res);
    Assert.notNull(res.getInner());
    Assert.assertEquals( ..., res.getInner() );
}

2
Ve bu iyi bir şey, testlerinizde herhangi bir şartlı mantığa sahip olmamalısınız. Testi daha karmaşık ve daha az okunabilir yapar. Ve sanırım Roy blog yazısında, bir nesnede birden fazla iddia olduğunu her zaman tamam olduğunu belirtti. Öyleyse sahip olduklarınız sadece gardiyan iddialar ve onlara sahip olmak tamam.
Restuta

2
Siz Assert.notNullgereksiz, testiniz boşsa NPE ile başarısız olur.
sara

1
Ayrıca, ilk örnek (ile ifvarsa) geçecek resolannull
sara

1
@kai notNull's gereksiz, aynı fikirdeyim ama istisna yerine
iddiamın

1
Eh, başarısız bir iddia da bir istisna atar ve her iki durumda da, beraberinde bir yığın iziyle fırlatan tam sıra ile doğrudan bir bağlantı elde edersiniz, bu yüzden kişisel olarak testi yine de kontrol edilecek önkoşullarla karıştırmamayı tercih ederim. Assert.assertEquals(..., service.process().getInner());Satır "çok uzun" olursa, oneliner à la'yı , çıkarılan değişkenlerle mümkün kılmak isterdim
sara

6

Bir testin yalnızca bir nedenden dolayı başarısız olması gerektiği kuralında birden fazla iddia yazmanın geçerli olduğu birçok durum olduğunu düşünüyorum.

Örneğin, bir tarih dizesini ayrıştıran bir işlev hayal edin:

function testParseValidDateYMD() {
    var date = Date.parse("2016-01-02");

    Assert.That(date.Year).Equals(2016);
    Assert.That(date.Month).Equals(1);
    Assert.That(date.Day).Equals(0);
}

Test başarısız olursa bir nedenden dolayı ayrıştırma yanlıştır. Bu testin üç farklı nedenden ötürü başarısız olabileceğini iddia ederseniz, IMHO'nun "bir neden" tanımınızda çok iyi taneli olacağını düşünüyorsunuz.


3

[Test] yönteminin kendisinde birden fazla iddiaya sahip olmanın iyi bir fikir olacağı bir durum bilmiyorum. İnsanların birden fazla iddiaya sahip olmasının ana nedeni, test edilen her sınıf için bir tane [TestFixture] sınıfına sahip olmaya çalışıyor olmalarıdır. Bunun yerine, testlerinizi daha fazla [TestFixture] sınıfına ayırabilirsiniz. Bu, yalnızca ilk iddianın başarısız olduğu yer yerine, kodun beklediğiniz şekilde yanıt vermemiş olabileceği birden çok yolu görmenize olanak tanır. Bunu başarmanın yolu, içinde birçok [TestFixture] sınıfı ile test edilen sınıf başına en az bir dizininiz olmasıdır. Her [TestFixture] sınıfı, test edeceğiniz nesnenin belirli durumundan sonra adlandırılır. [SetUp] yöntemi nesneyi sınıf adıyla açıklanan duruma getirecektir. Daha sonra, nesnenin mevcut durumu göz önüne alındığında, her birinin gerçek olmasını beklediğiniz farklı şeyleri iddia eden çoklu [Test] yöntemlerine sahipsiniz. Her [Test] yöntemine, iddia ettiği şeyden sonra, belki de sadece kodu İngilizce okumak yerine, kavramdan sonra da adlandırması dışında adlandırılır. Sonra her bir [Test] metodu uygulamasında sadece bir şey iddia ettiği tek bir kod satırı gerekir. Bu yaklaşımın bir başka avantajı da testleri çok okunabilir hale getirmesidir, çünkü ne test ettiğinizi ve sadece sınıfa ve yöntem adlarına bakarak ne beklediğinizi net bir şekilde gösterir. Bu aynı zamanda, test etmek istediğiniz tüm küçük kenar durumlarını anlamaya başladığınızda ve hataları bulduğunuzda daha iyi ölçeklenir. Belki de sadece kodu İngilizce okumak yerine kavramdan sonra adlandırılabilir. Sonra her bir [Test] metodu uygulamasında sadece bir şey iddia ettiği tek bir kod satırı gerekir. Bu yaklaşımın bir başka avantajı da testleri çok okunabilir hale getirmesidir, çünkü ne test ettiğinizi ve sadece sınıfa ve yöntem adlarına bakarak ne beklediğinizi net bir şekilde gösterir. Bu aynı zamanda, test etmek istediğiniz tüm küçük kenar durumlarını anlamaya başladığınızda ve hataları bulduğunuzda daha iyi ölçeklenir. Belki de sadece kodu İngilizce okumak yerine kavramdan sonra adlandırılabilir. Sonra her bir [Test] metodu uygulamasında sadece bir şey iddia ettiği tek bir kod satırı gerekir. Bu yaklaşımın bir başka avantajı da testleri çok okunabilir hale getirmesidir, çünkü ne test ettiğinizi ve sadece sınıfa ve yöntem adlarına bakarak ne beklediğinizi net bir şekilde gösterir. Bu aynı zamanda, test etmek istediğiniz tüm küçük kenar durumlarını anlamaya başladığınızda ve hataları bulduğunuzda daha iyi ölçeklenir. ve ne sadece sınıf ve yöntem adlarına bakarak beklediğiniz. Bu aynı zamanda, test etmek istediğiniz tüm küçük kenar durumlarını anlamaya başladığınızda ve hataları bulduğunuzda daha iyi ölçeklenir. ve ne sadece sınıf ve yöntem adlarına bakarak beklediğiniz. Bu aynı zamanda, test etmek istediğiniz tüm küçük kenar durumlarını anlamaya başladığınızda ve hataları bulduğunuzda daha iyi ölçeklenir.

Genellikle bu, [SetUp] yönteminin içindeki son kod satırının, [TestFixture] öğesinin özel bir değişkeninde bir özellik değeri veya değer döndürmesi gerektiği anlamına gelir. Ardından, bu örnek değişken hakkında farklı [Test] yöntemlerinden farklı birçok şey iddia edebilirsiniz. Ayrıca, test edilen nesnenin hangi özelliklerinin şimdi istenen durumda olduğu konusunda ayarlandığı konusunda da iddialarda bulunabilirsiniz.

Bazen nesneyi istenen duruma getirmeden önce karışmadığınızdan emin olmak için teste tabi tutulan nesneyi istenen duruma getirirken yol boyunca iddialarda bulunmanız gerekir. Bu durumda, bu ekstra iddialar [SetUp] yönteminde görünmelidir. [SetUp] yönteminde bir şeyler ters giderse, nesne test etmek istediğiniz istediğiniz duruma gelmeden önce testte bir şeylerin yanlış olduğu açıktır.

Karşılaşabileceğiniz diğer bir sorun, atılmayı bekleyen bir İstisna'yı test ediyor olabilirsiniz. Bu, yukarıdaki modeli takip etmeme konusunda sizi cezbedebilir. Bununla birlikte, [SetUp] yöntemindeki istisnayı yakalayarak ve bir örnek değişkeninde saklayarak yine de elde edilebilir. Bu, her biri kendi [Test] yönteminde istisna hakkında farklı şeyler iddia etmenize olanak sağlar. Daha sonra atılan istisnadan istenmeyen hiçbir yan etki olmadığından emin olmak için test edilen nesne hakkında başka şeyler de iddia edebilirsiniz.

Örnek (bu birden fazla dosyaya bölünür):

namespace Tests.AcctTests
{
    [TestFixture]
    public class no_events
    {
        private Acct _acct;

        [SetUp]
        public void SetUp() {
            _acct = new Acct();
        }

        [Test]
        public void balance_0() {
            Assert.That(_acct.Balance, Is.EqualTo(0m));
        }
    }

    [TestFixture]
    public class try_withdraw_0
    {
        private Acct _acct;
        private List<string> _problems;

        [SetUp]
        public void SetUp() {
            _acct = new Acct();
            Assert.That(_acct.Balance, Is.EqualTo(0));
            _problems = _acct.Withdraw(0m);
        }

        [Test]
        public void has_problem() {
            Assert.That(_problems, Is.EquivalentTo(new string[] { "Withdraw amount must be greater than zero." }));
        }

        [Test]
        public void balance_not_changed() {
            Assert.That(_acct.Balance, Is.EqualTo(0m));
        }
    }

    [TestFixture]
    public class try_withdraw_negative
    {
        private Acct _acct;
        private List<string> _problems;

        [SetUp]
        public void SetUp() {
            _acct = new Acct();
            Assert.That(_acct.Balance, Is.EqualTo(0));
            _problems = _acct.Withdraw(-0.01m);
        }

        [Test]
        public void has_problem() {
            Assert.That(_problems, Is.EquivalentTo(new string[] { "Withdraw amount must be greater than zero." }));
        }

        [Test]
        public void balance_not_changed() {
            Assert.That(_acct.Balance, Is.EqualTo(0m));
        }
    }
}

Bu durumda TestCase girişini nasıl kullanırsınız?
Simon Gillbee

Dolayısıyla, şu anki organizasyonumda, gösterdiklerinize çok benzeyen 20.000+ birim testimiz var. Bu bir kabus. Test kurulum kodunun çoğu kopyalanır / yapıştırılır, bu da hatalı test ayarına ve geçersiz testlere neden olur. Her [Test]yöntem için, o sınıf yeniden başlatılır ve [SetUp]yöntem yeniden yürütülür. Bu, .NET Çöp Toplayıcı'yı öldürür ve testlerin çok yavaş çalışmasına neden olur: yerel olarak 5+ dakika, yapı sunucusunda 20+ dakika. 20K testleri yaklaşık 2-3 dakika içinde yapılmalıdır. Ben ediyorum değil özellikle büyük imsi test paketi için, hiç bu test tarzı önerilir.
fourpastmidnight

@fourpastmidnight, söylediklerinizin çoğu geçerli eleştiri gibi görünüyor, ancak kurulum kodunu kopyalayıp yapıştırma ve bu nedenle yanlış olma konusu, bu bir yapı sorunu değil, sorumsuz programcıların (sorumsuz yöneticilerin veya olumsuz bir ortamın sonucu olabilecek) kötü programcılardan çok daha fazlası). Eğer insanlar sadece kodu kopyalayıp yapıştırabilirler ve doğru olduğunu umarlarsa ve kodu anlamak için canlarını sıkmazlarsa, herhangi bir nedenle, herhangi bir nedenden ötürü, ya bunu yapmamak için eğitilmeleri gerekir veya kullanılamazlarsa serbest bırakılmaları gerekir. eğitimli. Her iyi programlama ilkesine aykırıdır.
still_dreaming_1

Ancak genel olarak, kabul ediyorum, bu her türlü soruna yol açacak çok sayıda şişkinlik / bagaj / çoğaltma ile sonuçlanacak olan çılgın bir fazlalık. Eskiden deliydim ve bunun gibi şeyler öneririm. Daha önce ertesi gün kendimle ilgili her gün söyleyebilmeyi umduğum şey bu çünkü daha iyi şeyler yapmayı asla bırakmayacağım anlamına geliyor.
still_dreaming_1

@ still_dreaming_1 "sorumsuz programcılar" ile: Bu davranışın büyük bir sorun olduğuna katılıyorum. Ancak, bu tür bir test yapısı gerçekten daha iyi veya daha kötüsü için bu tür davranışları davet ediyor. Kötü gelişim uygulamaları bir yana, bu forma temel itirazım, test performansını gerçekten öldürmesidir. Yavaş çalışan bir test odasından daha kötü bir şey yok. Yavaş çalışan bir test paketi, insanların yerel olarak testler yapamayacakları ve hatta ara binalara atlamak için cazip oldukları anlamına gelir - yine bir insan problemi, ancak olur - bunların hepsi hızlı koşma testlerinin başlamasını sağlamak suretiyle önlenebilir. ile.
fourpastmidnight 4

2

Aynı testte birden fazla iddiaya sahip olmak, yalnızca test başarısız olduğunda bir sorundur. Öyleyse, testte hata ayıklamanız veya hangi iddianın başarısız olduğunu bulmak için istisnayı analiz etmeniz gerekebilir. Her testte yapılan bir iddia ile, neyin yanlış olduğunu tespit etmek genellikle daha kolaydır.

Birden fazla iddiaya gerçekten ihtiyaç duyulan bir senaryo düşünemiyorum , çünkü bunları her zaman aynı iddiada birden fazla koşul olarak yeniden yazabilirsiniz. Bununla birlikte, örneğin, daha sonraki adımların hatalı girdi nedeniyle çökmesi riskini almak yerine, ara verileri doğrulamak için birkaç adımınız varsa tercih edilebilir.


1
Birden fazla koşulu tek bir iddiada birleştiriyorsanız, başarısızlık durumunda tek bildiğiniz başarısızlığın olduğu. Birden fazla iddia ile özellikle bunlardan bazılarını tanırsınız (başarısızlığa kadar olanlar da dahil). Döndürülen bir dizinin tek bir değer içerdiğini kontrol etmeyi göz önünde bulundurun: boş olmadığını kontrol edin, sonra tam olarak bir öğeye ve sonra o öğenin değerini kontrol edin. (Platforma bağlı olarak) sadece değeri hemen kontrol etmek, boş bir referans değeri verebilir (boş bırakma başarısızlığından daha az yardımcı olabilir) ve dizi uzunluğunu kontrol etmez.
Richard,

@Richard: Bir sonuç almak ve daha sonra bu sonuçtan bir şeyler çıkarmak birkaç adımda bir işlem olabilir, bu yüzden cevabı ikinci paragrafta ele aldım.
Guffa

2
Temel kural: Testte birden fazla iddia varsa, her birinin farklı bir mesajı olmalıdır. O zaman bu sorunun yok.
Anthony

NCrunch gibi kaliteli bir test çalıştırıcısı kullanmak hem test kodunda hem de test edilen kodda testin hangi satırda yapıldığını tam olarak gösterecektir.
fourpastmidnight

2

Testiniz başarısız olursa, aşağıdaki iddiaların da geçerli olup olmayacağını bilemezsiniz. Çoğu zaman, bu sorunun kaynağını bulmak için değerli bilgilerinizin eksik olacağı anlamına gelir. Benim çözümüm, bir assert kullanmak, ancak birkaç değeri var:

String actual = "val1="+val1+"\nval2="+val2;
assertEquals(
    "val1=5\n" +
    "val2=hello"
    , actual
);

Bu, tüm başarısız iddiaları bir kerede görmemi sağlıyor. Birkaç satır kullanıyorum çünkü çoğu IDE yan yana bir karşılaştırma diyalogunda string farklılıkları gösterecek.


2

Tek bir test fonksiyonunda birden fazla değerlendirme varsa, onların yaptığınız testle doğrudan alakalı olmalarını bekliyorum. Örneğin,

@Test
test_Is_Date_segments_correct {

   // It is okay if you have multiple asserts checking dd, mm, yyyy, hh, mm, ss, etc. 
   // But you would not have any assert statement checking if it is string or number,
   // that is a different test and may be with multiple or single assert statement.
}

Çok fazla test yaptırmak (bunun muhtemelen fazladan bir engel olduğunu düşünüyorsanız bile) kötü bir şey değildir. En önemli ve hayati testlere sahip olmanın daha önemli olduğunu söyleyebilirsiniz. Öyleyse, iddiada bulunurken, çok fazla iddiadan endişe etmek yerine, iddialı ifadelerinizin doğru yerleştirildiğinden emin olun. Birden fazla kişiye ihtiyacınız varsa, birden fazla kullanın.


1

Birim testinin amacı, sizi neyin başarısız olduğu konusunda mümkün olduğunca fazla bilgi vermek ve aynı zamanda ilk önce en temel sorunları doğru şekilde belirlemenize yardımcı olmaktır. Mantıksal olarak bildiğiniz zaman, başka bir iddianın başarısız olduğu veya bir başka deyişle test arasında bir bağımlılık ilişkisi olduğu düşünüldüğünde bir iddianın başarısız olacağını, ardından bunları tek bir test içinde çoklu testler olarak döndürmenin bir anlamı vardır. Bu, test sonuçlarını tek bir testte ilk iddiadan kurtulduğumuzda elimine edilemeyecek belirgin hatalarla sınırlandırmamak avantajına sahiptir. Bu ilişkinin olmadığı durumlarda, doğal olarak bu iddiaları bireysel testlere ayırmak tercih edilir, çünkü aksi halde bu hataları bulmak, tüm sorunları çözmek için birden fazla test çalıştırması yinelemesi gerektirecektir.

Ayrıca, üniteleri / sınıfları aşırı karmaşık testlerin yazılması gerekecek şekilde tasarlarsanız, test sırasında daha az yük oluşturur ve muhtemelen daha iyi bir tasarım sağlar.


1

Evet, başarısız bir test size arızayı teşhis edebilmeniz için yeterli bilgi sağladığı sürece birçok iddiada bulunmak mümkündür . Bu ne test ettiğinize ve arıza modlarının ne olduğuna bağlı olacaktır.

Doğru birim testleri tam olarak bir nedenden ötürü başarısız olmalıdır, bu yüzden birim test başına bir onay kullanmalısınız.

Bu tür formülasyonları yararlı bulmamıştım (bir sınıfın değişmesi için bir nedene sahip olması gerektiği gibi işe yaramayan bir özne örneğidir). İki dizenin eşit olduğu iddiasını göz önünde bulundurun, bu iki dizenin uzunluğunun aynı olduğunu ve karşılık gelen dizindeki her karakterin eşit olduğunu iddia etmek için anlamsal olarak eşdeğerdir.

Herhangi bir çoklu değerlendirme sisteminin tek bir iddia olarak yeniden yazılabileceğini ve herhangi bir tek bir iddianın daha küçük bir tasfiye grubuna ayrılabileceğini söyleyebiliriz.

Bu nedenle, sadece kodun netliğine ve test sonuçlarının netliğine odaklanın ve bunun tersini kullanmak yerine kullandığınız iddiaların sayısını yönlendirmesine izin verin.


0

Cevap çok basittir - aynı nesnenin birden fazla niteliğini, aynı nesnenin ve hatta iki farklı nesneyi değiştiren bir işlevi test ediyorsanız ve işlevin doğruluğu, tüm bu değişikliklerin sonuçlarına bağlıdır, o zaman iddia etmek istediğinizde bu değişikliklerin her birinin uygun şekilde yapıldığını!

Mantıksal bir kavram fikrini anlıyorum, ancak bunun tersi bir sonuç hiçbir işlevin birden fazla nesneyi değiştirmemesi gerektiğini söyleyecektir. Ancak bu, her durumda, benim deneyimime göre uygulamak imkansız.

Bir banka işleminin mantıksal kavramını alın - çoğu durumda bir banka hesabından bir miktarın çekilmesi, bu tutarın başka bir hesaba eklenmesini zorunlu kılar. Bu iki şeyi ASLA ayırmak istemezsiniz, atomik bir birim oluştururlar. Ek olarak, iki işlev yapmak (çekilmek / addMoney) yapmak ve böylece iki farklı birim testi yazmak isteyebilirsiniz. Ancak bu iki işlemin bir işlem içinde gerçekleştirilmesi gerekir ve ayrıca işlemin çalıştığından emin olmak istersiniz. Bu durumda, bireysel adımların başarılı olduğundan emin olmak yeterli değildir. Testinizde her iki banka hesabını da kontrol etmeniz gerekiyor.

Birim bir testte, ilk etapta değil, bir entegrasyon veya kabul testinde test edemeyeceğiniz daha karmaşık örnekler olabilir. Ancak bu sınırlar akıcıdır, IMHO! Karar vermek o kadar kolay değil, şartlar ve belki kişisel tercih meselesi. Birinden para çekmek ve başka bir hesaba eklemek hala çok basit bir işlev ve kesinlikle birim testi için aday.


-1

Bu soru spagetti ve lazanya kod sorunları arasındaki klasik dengeleme sorunu ile ilgilidir.

Birden fazla değerlendirme yapılması, testin ne hakkında olduğu hakkında bir fikrinizin olmadığı spagetti problemine kolayca girebilir, ancak test başına tek bir onaylama yapılması, testinizin büyük bir lazanyada birden fazla teste sahip olmasının testin ne kadar imkansız olduğunu bulmasını sağlar. .

Bazı istisnalar var, ancak bu durumda sarkaç ortada tutulması cevaptır.


-3

Genel olarak "sadece bir nedenle başarısız" ile aynı fikirde değilim. Daha da önemlisi, testlerin kısa ve açıkça imo okuduğu.

Ancak bu her zaman elde edilemez ve bir test karmaşık olduğunda (uzun) tanımlayıcı bir isim ve daha az şeyi test etmek daha anlamlı olur.

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.