Mengapa saya harus menggunakan Hamcrest-Matcher dan assertThat () bukannya assertXXX tradisional () - Metode

153

Ketika saya melihat contoh di kelas Assert JavaDoc

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

Saya tidak melihat keuntungan besar, katakanlah assertEquals( 0, 1 ),.

Sangat menyenangkan mungkin untuk pesan jika konstruksinya menjadi lebih rumit tetapi apakah Anda melihat lebih banyak keuntungan? Keterbacaan?

Peter Kofler
sumber

Jawaban:

172

Tidak ada keuntungan besar untuk kasus-kasus di mana assertFooada yang tepat sesuai dengan niat Anda. Dalam kasus-kasus itu mereka berperilaku hampir sama.

Tetapi ketika Anda datang ke cek yang agak lebih kompleks, maka keuntungannya menjadi lebih terlihat:

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

vs.

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

Orang dapat mendiskusikan mana dari mereka yang lebih mudah dibaca, tetapi setelah pernyataan itu gagal, Anda akan mendapatkan pesan kesalahan yang bagus assertThat, tetapi hanya sejumlah kecil informasi assertTrue.

assertThatakan memberi tahu Anda apa pernyataannya dan apa yang Anda dapatkan. assertTruehanya akan memberi tahu Anda bahwa Anda mencapai apa yang falseAnda harapkan true.

Joachim Sauer
sumber
Saya memiliki pertanyaan ini juga di benak saya. Terima kasih, saya tidak pernah memikirkannya dengan cara ini.
wheaties
1
Ini juga membantu dengan "aturan" satu pernyataan per pengujian dan lebih mudah berpadu dengan spesifikasi gaya BDD.
Nils Wloka
2
Dan itu memisahkan mekanisme pernyataan dari kondisi (yang menyebabkan pesan kesalahan lebih baik).
SteveD
2
Contohnya tidak masuk akal karena hampir tidak ada yang akan menggunakan satu assertTruedengan &&. Memisahkannya menjadi dua kondisi membuat masalah menjadi jelas bahkan di JUnit. Jangan salah sangka; Saya setuju dengan Anda, saya hanya tidak suka teladan Anda.
maaartinus
48

Catatan rilis JUnit untuk versi 4.4 (saat diperkenalkan) menyatakan empat keuntungan:

  • Lebih mudah dibaca dan diketik: sintaks ini memungkinkan Anda untuk berpikir dalam hal subjek, kata kerja, objek (menyatakan "x adalah 3") daripada assertEquals , yang menggunakan kata kerja, objek, subjek (menyatakan "sama dengan 3 x")
  • Kombinasi: pernyataan pencocokan apa pun dapat dinegasikan ( bukan ), digabungkan ( baik) atau (t) ), dipetakan ke koleksi ( masing-masing ), atau digunakan dalam kombinasi khusus (setelah FiveSeconds (s)) )
  • Pesan kegagalan yang bisa dibaca. (...)
  • Pencocokan Kustom. Dengan menerapkan antarmuka Matcher sendiri, Anda bisa mendapatkan semua manfaat di atas untuk pernyataan kustom Anda sendiri.

Argumentasi lebih rinci dari orang yang membuat sintaks baru: di sini .

Manur
sumber
39

Pada dasarnya untuk meningkatkan keterbacaan kode .

Selain hamcrest, Anda juga dapat menggunakan pernyataan fest . Mereka memiliki beberapa keunggulan dibandingkan hamcrest seperti:

Beberapa contoh

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));

Pembaruan 17 Oktober 2016

Fest sudah tidak aktif lagi, gunakan AssertJ sebagai gantinya.

Igor Popov
sumber
4
Fest tampaknya telah mati, tetapi garpu Assert sangat hidup.
Amedee Van Gasse
18

Pembenaran yang sangat mendasar adalah bahwa sulit untuk mengacaukan sintaks baru.

Misalkan nilai tertentu, foo, harus 1 setelah tes.

assertEqual(1, foo);

--ATAU--

assertThat(foo, is(1));

Dengan pendekatan pertama, sangat mudah untuk melupakan urutan yang benar, dan mengetiknya mundur. Kemudian daripada mengatakan bahwa tes gagal karena diharapkan 1 dan mendapat 2, pesannya terbalik. Bukan masalah ketika tes lulus, tetapi dapat menyebabkan kebingungan ketika tes gagal.

Dengan versi kedua, hampir tidak mungkin membuat kesalahan ini.

Andy Davis
sumber
... dan ketika Eclipse melaporkan kegagalan pernyataan, jika Anda menempatkan argumen dengan cara yang salah di tradisional assertThat (), kesalahan tersebut tidak masuk akal.
Sridhar Sarnobat
9

Contoh:

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. Anda dapat membuat tes Anda lebih khusus
  2. Anda mendapatkan Pengecualian yang lebih rinci, jika tes gagal
  3. lebih mudah untuk membaca Tes

btw: Anda juga bisa menulis Teks di assertXXX ...

MartinL
sumber
1
Lebih baik lagi, saya akan mengabaikan argumen string dalam assertThatkasus ini, karena pesan yang Anda dapatkan secara otomatis sama informatif: "Diharapkan: (nilai lebih besar dari <1> dan nilai kurang dari <3>)"
MatrixFrog
Ya kamu benar. Saya mengedit jawaban saya. Awalnya saya ingin menggunakan keduanya (Matcher) .dan (Matcher) tetapi tidak berhasil.
MartinL
3
assertThat(frodo.getName()).isEqualTo("Frodo");

Dekat dengan bahasa alami.

Lebih mudah dibaca, lebih mudah menganalisis kode. Programer menghabiskan lebih banyak waktu untuk menganalisis kode daripada menulis yang baru. Jadi jika kode akan mudah dianalisis maka pengembang harus lebih produktif.

Kode PS harus menjadi buku yang ditulis dengan baik. Kode yang didokumentasikan sendiri.

pengguna4515828
sumber
4
OK dan…? Saya sarankan mendukung argumen Anda dengan menjelaskan mengapa itu hal yang baik.
Nathan Tuggy
0

ada keuntungan untuk menegaskan bahwa lebih dari assertEquals -
1) lebih mudah dibaca
2) informasi lebih lanjut tentang kegagalan
3) kompilasi kesalahan waktu - daripada kesalahan waktu berjalan
4) fleksibilitas dengan kondisi pengujian penulisan
5) portabel - jika Anda menggunakan hamcrest - Anda dapat menggunakan jUnit atau TestNG sebagai kerangka kerja yang mendasarinya.

Samers
sumber