CodeGym /Java Blog /Acak /Pengujian Unit di Java dengan JUnit
John Squirrels
Level 41
San Francisco

Pengujian Unit di Java dengan JUnit

Dipublikasikan di grup Acak

Apa itu pengujian unit di Jawa?

Sebelum kita mempelajari JUnit di Java, mari kita tinjau secara singkat apa itu pengujian unit dan mengapa ini sangat populer (jika Anda sudah mengetahui hal ini, lewati ke 'Bagaimana cara menulis Tes JUnit di Java?'). Pengujian unit di Java membuat pengembangan perangkat lunak skala besar jauh lebih efisien dan mudah. Ini dapat membantu individu, dan tim memotong banyak waktu dari debugging dan sangat merampingkan proses kolaborasi. Pengujian Unit di Java dengan JUnit - 1

https://junit.org/junit4/

Ide penting dari pengujian unit adalah ini: tulis pengujian atomik dari fitur individual (disebut pengujian unit) dan perlahan tambahkan lebih banyak fitur setelah pengujian dan pastikan yang sebelumnya berfungsi. Ini adalah ide yang sangat sederhana namun kuat. Sebagai contoh bagaimana proses ini terlihat, bayangkan Anda sedang membuat kalkulator ilmiah virtual. Selain operator aritmetika ( +, -, x, %), kalkulator ini memiliki fitur canggih yang memerlukan subfitur lain untuk bekerja di dalamnya. Untuk menghitung eksponen, kalkulator Anda harus dapat mengalikan dengan benar. Jadi pendekatan pengujian unit untuk membangun dan menguji kalkulator ini adalah:
  • Tulis fungsi penjumlahan. Uji dengan hati-hati, ubah, ulangi hingga berhasil.
  • Lakukan hal yang sama untuk fungsi pengurangan, perkalian, pembagian.
  • Gunakan operator dasar ini untuk menulis fungsi operator lanjutan seperti eksponen, lalu uji juga fungsi tersebut.
Hal ini memastikan bahwa fitur yang membangun subfitur lain yang lebih kecil tidak hanya berfungsi dengan baik dengan sendirinya tetapi tidak memiliki subfitur yang salah di dalamnya. Misalnya, jika saya menguji fungsi eksponen dan ada yang tidak beres, saya tahu bahwa bug tersebut mungkin tidak ada di subfitur perkalian, karena fungsi perkalian sudah diuji secara ekstensif. Ini sangat menghilangkan jumlah kode yang saya butuhkan untuk menelusuri kembali dan memeriksa untuk menemukan bug. Mudah-mudahan, contoh sepele ini memperjelas bagaimana proses pemikiran seputar Unit Testing disusun. Tetapi bagaimana pengujian unit berinteraksi dengan proses pengembangan perangkat lunak lainnya? Bagaimana jika Anda memiliki fitur yang lebih kompleks, yang harus dapat bekerja dan berkomunikasi bersama? Pengujian unit tidak cukup untuk memastikan bahwa fitur kompleks tersebut dapat bekerja sama dengan baik. Faktanya, ini hanyalah langkah pertama dari Empat Tingkat Pengujian Perangkat Lunak (saya menggunakan huruf kapital karena saya mengacu pada standar industri atau pendekatan yang paling umum untuk menguji perangkat lunak). Tiga langkah terakhir adalahPengujian Integrasi , Pengujian Sistem , dan Pengujian Penerimaan. Ini semua mungkin berarti persis seperti yang Anda pikirkan, tetapi izinkan saya mengklarifikasi: Pengujian integrasi adalah apa yang akan kami lakukan untuk memastikan hal-hal yang disebutkan di atas, "fitur kompleks", berinteraksi dengan baik satu sama lain. (misalnya, memastikan kalkulator dapat menangani “3 + 7 * 4 - 2”) Pengujian sistem adalah pengujian desain keseluruhan dari sistem tertentu; sering ada beberapa sistem dengan fitur kompleks yang bekerja bersama dalam suatu produk, jadi Anda mengelompokkannya ke dalam sistem dan mengujinya satu per satu. (misalnya jika Anda membuat kalkulator grafik, pertama-tama Anda akan membangun 'sistem' aritmatika untuk menangani angka, mengujinya hingga berfungsi sebagaimana mestinya, dan kemudian Anda akan membangun dan menguji 'sistem' grafik untuk menangani penarikan, sebagai itu akan membangun dari sistem aritmatika). Pengujian penerimaan adalah pengujian tingkat pengguna; itu melihat apakah semua sistem dapat bekerja secara sinkron untuk membuat produk jadi yang siap diterima oleh pengguna (mis., pengguna menguji kalkulator). Pengembang perangkat lunak terkadang dapat mengabaikan langkah terakhir dari proses ini, karena perusahaan sering kali meminta karyawan lain untuk menerapkan pengujian pengguna (beta) secara terpisah.

Bagaimana cara menulis tes JUnit di Java?

Sekarang setelah Anda memiliki gagasan yang lebih jelas tentang manfaat dan batasan pengujian unit, mari kita lihat beberapa kode! Kami akan menggunakan kerangka pengujian Java populer yang disebut JUnit (yang populer lainnya adalah TestNG, yang juga dapat Anda gunakan jika Anda mau. Mereka sangat mirip, secara sintaksis; TestNG terinspirasi oleh JUnit). Anda dapat mengunduh dan menginstal JUnit di sini . Untuk kode contoh ini, kita akan melanjutkan contoh 'kalkulator ilmiah' yang saya sebutkan sebelumnya; cukup sederhana untuk membungkus kepala Anda, dan kode pengujiannya sangat mudah. Praktik konvensional adalah menulis kelas tes terpisah untuk setiap kelas Anda, jadi itulah yang akan kami lakukan. Mari kita asumsikan bahwa pada titik ini, kita memiliki sebuah Math.javafile dengan semua fungsi matematika di dalamnya (termasuk Math.add), dan kita sedang menulis sebuahMathTests.javafile dalam paket yang sama. Sekarang mari kita siapkan pernyataan impor dan isi kelas: (PERTANYAAN WAWANCARA JUnit MUNGKIN: Anda mungkin ditanya di mana menempatkan pengujian JUnit Anda dan apakah Anda perlu mengimpor file sumber atau tidak. Jika Anda menulis kelas pengujian dalam paket yang sama dengan kelas utama Anda, maka Anda tidak memerlukan pernyataan impor apa pun untuk file sumber Anda di kelas pengujian. Jika tidak, pastikan Anda mengimpor file sumber Anda!)

import org.junit.jupiter.Test;    //gives us the @Test header
import static org.junit.jupiter.api.Assertions.assertEquals; //less typing :) 

public class MathTests {
	//...
}
Pernyataan import pertama memberi kita header @Test. Kami menulis ' @Test' langsung di atas setiap definisi fungsi pengujian, sehingga JUnit mengetahui bahwa ini adalah pengujian unit tunggal yang dapat dijalankan secara terpisah. Nanti, saya akan menunjukkan kepada Anda bagaimana Anda dapat menjalankan tes unit tertentu menggunakan header ini. Pernyataan impor kedua menghemat sedikit pengetikan. Fungsi JUnit utama yang kami gunakan untuk menguji fungsi kami adalah to Assert.assertEquals(), yang mengambil dua parameter (nilai aktual dan nilai yang diharapkan) dan memastikan keduanya sama. Memiliki pernyataan impor kedua ini memungkinkan kita untuk mengetik ' assertEquals(...' alih-alih harus menentukan setiap kali paket mana yang menjadi bagiannya. Sekarang mari kita tulis kasus uji yang sangat sederhana untuk memverifikasi bahwa 2 + 2 memang 4!

import org.junit.jupiter.Test; // gives us the @Test header
import static org.junit.jupiter.api.Assertions.assertEquals; // less typing :) 


public class MathTests {
	@Test
	public void add_twoPlusTwo_returnsFour(){
	final int expected = 4;
	final int actual = Math.add(2, 2);
	assertEquals(“2+2 is 4”, actual, expected);
	}
}
Mari kita bahas masing-masing dari lima baris fungsi pengujian dan apa fungsinya: Baris 5: @TestHeader ini menetapkan bahwa definisi fungsi di bawah add_twoPlusTwo_returnsFour()memang merupakan fungsi pengujian yang dapat dijalankan JUnit secara terpisah. Baris 6: Ini adalah tanda tangan fungsi untuk kasus pengujian kami. Test case selalu sangat unik; mereka hanya menguji satu contoh spesifik, seperti 2+2=4. Merupakan konvensi untuk menamai kasus pengujian Anda dalam bentuk " [function]_[params]_returns[expected]()," di mana [function]nama fungsi yang Anda uji, [params]adalah parameter contoh spesifik yang Anda uji, dan [expected]merupakan nilai hasil yang diharapkan dari fungsi tersebut. Fungsi pengujian hampir selalu memiliki tipe pengembalian ' void' karena tujuan utama dari keseluruhan fungsi adalah menjalankanassertEquals, yang akan ditampilkan ke konsol apakah tes Anda lulus atau tidak; Anda tidak memerlukan data lain untuk dikembalikan ke mana pun. Baris 7: Kita mendeklarasikan finalvariabel ' ' dengan tipe kembalian Math.add (int), dan menamainya 'diharapkan' berdasarkan konvensi. Nilainya adalah jawaban yang kita harapkan (4). Baris 8: Kita mendeklarasikan finalvariabel ' ' dengan tipe pengembalian Math.add (int), dan menamakannya 'aktual' berdasarkan konvensi. Nilainya adalah hasil dari Math.add(2, 2). Baris 9: Garis emas. Ini adalah garis yang membandingkan aktual dan yang diharapkan dan memberi tahu kita bahwa kita lulus ujian hanya jika keduanya sama. Parameter pertama yang lulus “2+2 is 4” adalah deskripsi dari fungsi pengujian.

Bagaimana jika fungsi saya harus mengeluarkan pengecualian?

Jika contoh pengujian spesifik Anda harus mengeluarkan pengecualian alih-alih menyatakan bahwa nilai aktual dan yang diharapkan sama, maka JUnit memiliki cara untuk mengklarifikasi ini di header @Test. Mari kita lihat contoh di bawah ini. Dengan asumsi kita memiliki fungsi dalam Math.javacalls Math.divide, kita ingin memastikan bahwa input tidak dapat dibagi dengan 0. Sebagai gantinya, mencoba memanggil Math.divide(a, 0)nilai 'a' apa pun harus mengeluarkan pengecualian ( ArithmeticException.class). Kami menentukannya di header seperti itu:

import org.junit.jupiter.Test; // gives us the @Test header
import static org.junit.jupiter.api.Assertions.assertEquals; // less typing :) 


public class MathTests {
	@Test (expectedExceptions = ArithmeticException.class)
	public void divide_byZero_throwsException() throws ArithmeticException{
	Math.divide(1, 0);
	}
}
Anda dapat memiliki lebih dari satu pengecualian untuk expectedExceptions, pastikan untuk menggunakan tanda kurung dan koma untuk mencantumkan kelas pengecualian Anda, seperti:

expectedException = {FirstException.class, SecondException.class, … }

Bagaimana cara menjalankan pengujian JUnit saya di Java?

Cara menambahkan JUnit ke IntelliJ: https://stackoverflow.com/questions/19330832/setting-up-junit-with-intellij-idea Anda dapat menjalankan proyek seperti biasanya menjalankan pengujian. Menjalankan semua tes di kelas tes akan menjalankannya dalam urutan abjad. Di JUnit 5, Anda dapat menambahkan prioritas pada pengujian dengan menambahkan tag @Order. Sebuah contoh:

@TestMethodOrder(OrderAnnotation.class)
public class Tests {
…
@Test
@Order(2)
public void a_test() { … }

@Test
@Order (1)
public void b_test() { … }
…
}
Meskipun a_test()datang sebelum b_test()menurut abjad dan dalam kode, b_test()akan berjalan sebelum a_test()di sini, karena 1 datang sebelum 2 dalam Urutan. Jadi itu saja untuk dasar-dasar JUnit. Sekarang, mari kita bahas beberapa Pertanyaan Umum Wawancara JUnit, dan pelajari lebih lanjut tentang JUnit di sepanjang jalan!

Pertanyaan Wawancara JUnit (Informasi Tambahan)

Di sini saya telah mengumpulkan pertanyaan wawancara JUnit paling populer. Jika Anda memiliki sesuatu untuk ditambahkan — jangan ragu untuk melakukannya di komentar di bawah. T: Metode apa yang dapat Anda panggil dalam metode pengujian untuk secara otomatis gagal dalam pengujian? A: fail(“deskripsi kesalahan di sini!”); T: Anda sedang menguji kelas Anjing; untuk menguji objek Anjing, Anda perlu memberi contoh sebelum Anda dapat menjalankan pengujian pada objek tersebut. Jadi Anda menulis fungsi setUp() untuk membuat instance Anjing. Anda hanya ingin menjalankan fungsi ini sekali selama semua pengujian. Apa yang harus Anda letakkan tepat di atas tanda tangan fungsi setUp() agar JUnit mengetahui cara menjalankan setUp() sebelum menjalankan pengujian? A: @BeforeClass (@BeforeAll di JUnit 5) T:Apa yang harus menjadi tanda fungsi dari fungsi setUp() yang dijelaskan di atas? A: kekosongan statis publik. Setiap fungsi dengan @BeforeClass (@BeforeAll di JUnit 5) atau @AfterClass (@AfterAll di JUnit 5) harus statis. T: Anda telah selesai menguji kelas Anjing. Anda menulis fungsi void tearDown() yang membersihkan data dan mencetak informasi ke konsol setelah setiap pengujian. Anda ingin fungsi ini dijalankan setelah setiap pengujian. Apa yang harus Anda tempatkan tepat di atas tanda tangan fungsi tearDown() agar JUnit mengetahui cara menjalankan tearDown() setelah menjalankan setiap pengujian? A: @After (@AfterEach di JUnit 5)
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION