Neden geleneksel assertXXX () yerine Hamcrest-Matcher ve assertThat () yöntemlerini kullanmalıyım - Yöntemler


153

Assert sınıfındaki JavaDoc örneklerine baktığımda

assertThat("Help! Integers don't work", 0, is(1)); // fails:
// failure message:
// Help! Integers don't work
// expected: is <1> 
// got value: <0>
assertThat("Zero is one", 0, is(not(1))) // passes

Diyelim ki, üzerinde büyük bir avantaj görmüyorum assertEquals( 0, 1 ).

Yapılar daha karmaşık hale gelirse mesajlar için güzel olabilir, ancak daha fazla avantaj görüyor musunuz? Okunabilirlik?

Yanıtlar:


173

assertFooNiyetinize tam olarak uyan bir varlığın olduğu durumlar için büyük bir avantaj yoktur . Bu durumlarda neredeyse aynı davranırlar.

Ancak, biraz daha karmaşık olan kontrollere geldiğinizde, avantaj daha görünür hale gelir:

assertTrue(foo.contains("someValue") && foo.contains("anotherValue"));

vs.

assertThat(foo, hasItems("someValue", "anotherValue"));

Bunlardan hangisinin okunmasının daha kolay olduğu tartışılabilir, ancak bir kez iddia başarısız olursa, iyi bir hata mesajı alırsınız assertThat, ancak çok az miktarda bilgi alırsınız assertTrue.

assertThatsize iddianın ne olduğunu ve onun yerine ne aldığınızı söyleyecektir. assertTruesadece falsebeklediğiniz yere geldiğinizi söyleyecektir true.


Aklımın arkasında da bu soru vardı. Teşekkür ederim, hiç böyle düşünmemiştim.
vahşiler

1
Ayrıca test başına bir iddianın "kuralına" yardımcı olur ve BDD stili spesifikasyonlarla daha kolay karışır.
Nils Wloka

2
Ve iddia mekanizmasını durumdan ayırır (daha iyi hata mesajlarına yol açan şey budur).
SteveD

2
Örnek, hiç kimsenin bir assertTrueile bir tane kullanması neredeyse imkansızdır &&. Bunu iki koşula ayırmak problemi JUnit'te bile belirgin hale getirir. Beni yanlış anlamayın; Sana katılıyorum, sadece örneğini beğenmedim.
maaartinus

48

Sürüm 4.4 (tanıtıldığı yerde) için JUnit sürüm notları dört avantajı belirtir :

  • Daha okunabilir ve yazılabilir: Bu sözdizimi, fiil, nesne, konu (assert "3 x" e eşittir) kullanan assertEquals yerine konu, fiil, nesne ("x is 3" islemi ) açısından düşünmenizi sağlar.
  • Kombinasyonlar: herhangi bir eşleşme ifadesi yok edilebilir ( değil ), birleştirilebilir ( ya da (s) .veya (t) ), bir koleksiyona ( her bir) eşlenebilir veya özel kombinasyonlarda ( afterFiveSeconds (s)) kullanılabilir )
  • Okunabilir hata mesajları. (...)
  • Özel Eşleştiriciler. Matcher arayüzünü kendiniz uygulayarak, kendi özel iddialarınız için yukarıdaki tüm avantajlardan yararlanabilirsiniz.

Yeni sözdizimini yaratan adamdan daha ayrıntılı tartışma: burada .


39

Temel olarak kodun okunabilirliğini artırmak için .

Hamcrest'in yanı sıra festival iddialarını da kullanabilirsiniz . Onlar sahip birkaç avantajı hamcrest üzerinde örneğin:

Bazı örnekler

import static org.fest.assertions.api.Assertions.*;

// common assertions
assertThat(yoda).isInstanceOf(Jedi.class);
assertThat(frodo.getName()).isEqualTo("Frodo");
assertThat(frodo).isNotEqualTo(sauron);
assertThat(frodo).isIn(fellowshipOfTheRing);
assertThat(sauron).isNotIn(fellowshipOfTheRing);

// String specific assertions
assertThat(frodo.getName()).startsWith("Fro").endsWith("do")
                           .isEqualToIgnoringCase("frodo");

// collection specific assertions
assertThat(fellowshipOfTheRing).hasSize(9)
                               .contains(frodo, sam)
                               .excludes(sauron);


// map specific assertions (One ring and elves ring bearers initialized before)
assertThat(ringBearers).hasSize(4)
                       .includes(entry(Ring.oneRing, frodo), entry(Ring.nenya, galadriel))
                       .excludes(entry(Ring.oneRing, aragorn));

17 Ekim 2016 Güncellemesi

Festival artık aktif değil, bunun yerine AssertJ kullanın.


4
Fest öldü, ancak AssertJ çatalı çok canlı.
Amedee Van Gasse

18

Çok temel bir gerekçe, yeni sözdizimini karıştırmanın zor olmasıdır.

Bir testten sonra belirli bir değerin (foo) 1 olması gerektiğini varsayalım.

assertEqual(1, foo);

--VEYA--

assertThat(foo, is(1));

İlk yaklaşımla, doğru sırayı unutmak ve geriye doğru yazmak çok kolaydır. Daha sonra, testin 1 beklediğinden ve 2 aldığından dolayı başarısız olduğunu söylemek yerine, mesaj geriye doğru. Test geçtiğinde sorun değil, ancak test başarısız olduğunda karışıklığa neden olabilir.

İkinci versiyonda, bu hatayı yapmak neredeyse imkansızdır.


... ve Eclipse bir onaylama hatası bildirdiğinde, argümanları geleneksel assertThat () öğesine yanlış bir şekilde koyarsanız, hata mantıklı değildir.
Sridhar Sarnobat

9

Misal:

assertThat(5 , allOf(greaterThan(1),lessThan(3)));
//  java.lang.AssertionError:
//  Expected: (a value greater than <1> and a value less than <3>)
//       got: <5>
assertTrue("Number not between 1 and 3!", 1 < 5 && 5 < 3);
//  java.lang.AssertionError: Number not between 1 and 3!
  1. testlerinizi daha belirgin hale getirebilirsiniz
  2. testler başarısız olursa daha ayrıntılı bir İstisna elde edersiniz
  3. Testi okumak daha kolay

btw: assertXXX'te de Metin yazabilirsiniz ...


1
Daha da iyisi, assertThatdurumda dize bağımsız değişkenini
dışarıda bırakardım

Evet haklısın. Cevabımı düzenlerim. Özgün olarak hem (Matcher). Hem de (Matcher) kullanmak istiyorum ama işe yaramadı.
MartinL

3
assertThat(frodo.getName()).isEqualTo("Frodo");

Doğal dile yakındır.

Daha kolay okunur, daha kolay analiz edilir. Programcı kodu analiz etmek için yenisini yazmaktan daha fazla zaman harcar. Kodun analiz edilmesi kolay olacaksa, geliştirici daha verimli olmalıdır.

PS Kodu iyi yazılmış bir kitap olmalıdır. Kendinden belgelenmiş kod.


4
Tamam ve…? Bunun neden iyi bir şey olduğunu açıklayarak tartışmanızı desteklemenizi tavsiye ederim.
Nathan Tuggy

0

assertEquals -
1) daha okunabilir
2) hata hakkında daha fazla bilgi
3) derleme zamanı hataları - çalışma zamanı hataları yerine
4) test koşulları yazma esnekliği
5) taşınabilir - hamcrest kullanıyorsanız - jUnit kullanabilirsiniz veya temel çerçeve olarak TestNG.

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.