CodeGym /Java Blogu /Rastgele /JUnit ile Java'da Birim Testi
John Squirrels
Seviye
San Francisco

JUnit ile Java'da Birim Testi

grupta yayınlandı

Java'da birim testi nedir?

JUnit'i Java'da öğrenmeye başlamadan önce, birim testinin ne olduğunu ve neden bu kadar popüler olduğunu kısaca gözden geçirelim (bu konuyu zaten biliyorsanız, 'Java'da JUnit Testi nasıl yazarım?' bölümüne geçin). Java'da birim testi, büyük ölçekli yazılım geliştirmeyi çok daha verimli ve zahmetsiz hale getirir. Hem bireylerin hem de ekiplerin sayısız saati hata ayıklamadan kurtarmasına ve işbirliği sürecini son derece modern hale getirmesine yardımcı olabilir. JUnit ile Java'da Birim Testi - 1

https://junit.org/junit4/

Birim testinin temel fikri şudur: bireysel özelliklerin atomik testlerini yazın (birim testleri olarak adlandırılır) ve testten sonra yavaş yavaş daha fazla özellik ekleyin ve öncekilerin çalışmasını sağlayın. Bu son derece basit ama güçlü bir fikir. Bu sürecin nasıl görünebileceğine bir örnek olarak, sanal bir bilimsel hesap makinesi yaptığınızı hayal edin. +Görünen aritmetik işleçlere ( , -, x, ) ek olarak %, bu hesap makinesi, içinde çalışmak için başka alt özellikler gerektiren gelişmiş özelliklere sahip olacaktır. Üsleri hesaplamak için hesap makinenizin doğru şekilde çarpabilmesi gerekir. Dolayısıyla, bu hesap makinesini oluşturmak ve test etmek için bir birim testi yaklaşımı şöyle olacaktır:
  • Bir toplama işlevi yazın. Dikkatlice test edin, değiştirin, çalışana kadar tekrarlayın.
  • Çıkarma, çarpma, bölme fonksiyonları için de aynısını yapın.
  • Üsler gibi daha gelişmiş operatör işlevleri yazmak için bu temel işleçleri kullanın, ardından bu işlevleri de test edin.
Bu, diğer daha küçük alt özellikleri oluşturan özelliklerin yalnızca kendi başlarına düzgün çalışmasını değil, aynı zamanda kendi içinde hatalı alt özelliklere sahip olmamasını sağlar. Örneğin, üs işlevini test ediyorsam ve bir şeyler ters gidiyorsa, hatanın muhtemelen çarpma alt özelliğinde olmadığını biliyorum çünkü çarpma işlevi zaten kapsamlı bir şekilde test edilmişti. Bu, hatayı bulmak için geriye doğru izlemem ve incelemem gereken toplam kod miktarını büyük ölçüde ortadan kaldırır. Umarız bu önemsiz örnek, Birim Testi etrafındaki düşünce sürecinin nasıl yapılandırıldığını netleştirir. Ancak birim testi, yazılım geliştirme sürecinin geri kalanıyla nasıl etkileşime girer? Ya birlikte çalışabilmesi ve iletişim kurabilmesi gereken daha karmaşık özellikleriniz varsa? Birim testi, bu tür karmaşık özelliklerin birlikte düzgün çalışmasını sağlamak için yetersizdir. Aslında, Yazılım Testinin Dört Düzeyi'nin yalnızca ilk adımıdır (Endüstri standardına veya test yazılımına yönelik en yaygın yaklaşıma atıfta bulunduğum için büyük harfler kullanıyorum). Son üç adımEntegrasyon Testi , Sistem Testi ve Kabul Testi. Bunların hepsi muhtemelen tam olarak düşündüğünüz şeyi ifade ediyor, ancak açıklığa kavuşturmama izin verin: Entegrasyon testi, yukarıda bahsedilen "karmaşık özelliklerin" birbirleriyle düzgün bir şekilde etkileşime girmesini sağlamak için yapacağımız şeydir. (örneğin, hesap makinesinin “3 + 7 * 4 - 2”yi işleyebileceğinden emin olmak) Sistem testi, belirli bir sistemin genel tasarımını test etmektir; genellikle bir üründe birlikte çalışan birden fazla karmaşık özellik sistemi vardır, bu nedenle bunları sistemler halinde gruplandırır ve ayrı ayrı test edersiniz. (örneğin, bir grafik hesap makinesi oluşturuyorsanız, önce sayılarla başa çıkmak için aritmetik 'sistemi' kurarsınız, amaçlandığı gibi çalışana kadar test edersiniz ve ardından, aşağıdaki gibi geri çekilmeyle başa çıkmak için grafik 'sistemini' oluşturur ve test edersiniz. aritmetik sistemden inşa ederdi). Kabul testi, kullanıcı düzeyinde testtir; kullanıcılar tarafından kabul edilmeye hazır bitmiş bir ürün oluşturmak için tüm sistemlerin senkronize çalışıp çalışamayacağını görmektir (örneğin, hesap makinesini test eden kullanıcılar). Şirketler genellikle diğer çalışanların kullanıcı (beta) testlerini ayrı ayrı dağıtmasını sağlayacağından, yazılım geliştiriciler bazen sürecin bu son adımını göz ardı edebilir.

JUnit testini Java'da nasıl yazarım?

Artık birim testinin faydaları ve sınırlamaları hakkında daha net bir fikriniz olduğuna göre, bazı kodlara göz atalım! JUnit adlı popüler bir Java test çerçevesi kullanacağız (diğer bir popüler olan TestNG'dir, isterseniz onu da kullanabilirsiniz. Sözdizimsel olarak çok benzerler; TestNG, JUnit'ten esinlenmiştir). JUnit'i buradan indirip kurabilirsiniz . Bu örnek kod için daha önce bahsettiğim 'bilimsel hesap makinesi' örneğinden devam edeceğiz; kafanızı karıştırmak oldukça basit ve test kodu süper kolay. Geleneksel uygulama, sınıflarınızın her biri için ayrı test sınıfları yazmaktır, yani yapacağımız şey bu. Diyelim ki bu noktada, Math.javaiçinde tüm matematik fonksiyonlarını ( dahil Math.add) içeren bir dosyamız var ve bir dosya yazıyoruz.MathTests.javaaynı pakette dosya. Şimdi import deyimlerini ve sınıf gövdesini ayarlayalım: (OLASI JUnit GÖRÜŞME SORUSU: JUnit testinizi nereye yerleştireceğiniz ve kaynak dosyalarınızı içe aktarmanız gerekip gerekmediği sorulabilir. ana sınıflarınız, o zaman test sınıfındaki kaynak dosyalarınız için herhangi bir içe aktarma ifadesine ihtiyacınız yoktur.Aksi takdirde, kaynak dosyalarınızı içe aktardığınızdan emin olun!)

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

public class MathTests {
	//...
}
İlk import ifadesi bize @Testbaşlığı verir. @TestJUnit'in bunun ayrı olarak çalıştırılabilen tekil bir birim testi olduğunu bilmesi için her test fonksiyonu tanımının üstüne doğrudan '' yazıyoruz . Daha sonra, bu başlığı kullanarak belirli birim testlerini nasıl çalıştırabileceğinizi size göstereceğim. İkinci import ifadesi bizi biraz yazmaktan kurtarıyor. İşlevlerimizi test etmek için kullandığımız birincil JUnit işlevi Assert.assertEquals(), iki parametre (gerçek değer ve beklenen değer) alan ve bunların eşit olmasını sağlayan to işlevidir. assertEquals(...Bu ikinci içe aktarma ifadesine sahip olmak , her seferinde hangi paketin parçası olduğunu belirtmek yerine '' yazmamıza izin verir . Şimdi 2 + 2'nin gerçekten 4 olduğunu doğrulamak için çok basit bir test durumu yazalım!

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);
	}
}
Test fonksiyonunun beş satırını ve ne yaptıklarını inceleyelim: 5. Satır: Bu @Testbaşlık, aşağıdaki fonksiyon tanımının add_twoPlusTwo_returnsFour()gerçekten JUnit'in ayrı olarak çalıştırabileceği bir test fonksiyonu olduğunu belirtir. Satır 6: Bu, test durumumuz için işlev imzasıdır. Test senaryoları her zaman çok tekildir; 2+2=4 gibi yalnızca belirli bir örneği test ederler. Test senaryolarınızı " " biçiminde adlandırmak gelenekseldir [function]_[params]_returns[expected](); burada [function]test ettiğiniz işlevin adı, [params]test ettiğiniz belirli örnek parametreler ve [expected]işlevin beklenen dönüş değeridir. Test işlevlerinin neredeyse her zaman bir dönüş türü ' void' ' vardır, çünkü tüm işlevin ana noktası çalıştırmaktır.assertEquals, testiniz başarılı olsun ya da olmasın konsola çıktı verecek; herhangi bir yere döndürülmek için başka herhangi bir veriye ihtiyacınız yoktur. final7. Satır: Dönüş türünün bir '' değişkenini bildiririz Math.add (int)ve onu kural gereği 'beklenen' olarak adlandırırız. Değeri, beklediğimiz cevaptır (4). final8. Satır: Dönüş türünün '' ' bir değişkenini bildiririz Math.add (int)ve bunu kural gereği 'gerçek' olarak adlandırırız. Değeri, sonucudur Math.add(2, 2). Satır 9: Altın çizgi. Bu, gerçek ile bekleneni karşılaştıran ve testi yalnızca eşitlerse geçtiğimizi söyleyen çizgidir. Geçilen ilk parametre "2+2 eşittir 4", test fonksiyonunun açıklamasıdır.

Ya işlevim bir istisna atarsa?

Spesifik test örneğiniz, gerçek ve beklenen bir değerin eşit olduğunu iddia etmek yerine bir istisna atarsa, JUnit'in bunu başlıkta açıklığa kavuşturmanın bir yolu vardır @Test. Aşağıda bir örneğe bakalım. Math.javacall içinde bir işlevimiz olduğunu varsayarsak Math.divide, girdilerin 0'a bölünemeyeceğinden emin olmak istiyoruz. Bunun yerine, Math.divide(a, 0)herhangi bir 'a' değeri çağırmaya çalışmak bir istisna ( ) atmalıdır ArithmeticException.class. Başlıkta şu şekilde belirtiyoruz:

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);
	}
}
için birden fazla istisnanız olabilir expectedExceptions, istisna sınıflarınızı listelemek için parantez ve virgül kullandığınızdan emin olun:

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

JUnit testlerimi Java'da nasıl çalıştırırım?

JUnit'i IntelliJ'e nasıl eklersiniz: https://stackoverflow.com/questions/19330832/setting-up-junit-with-intellij-idea Projenizi normalde testleri yaptığınız gibi çalıştırabilirsiniz. Tüm testleri bir test sınıfında çalıştırmak, onları alfabetik sırayla çalıştırır. JUnit 5'te, bir etiket ekleyerek testlere bir öncelik ekleyebilirsiniz @Order. Bir örnek:

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

@Test
@Order (1)
public void b_test() { … }
…
}
Alfabetik olarak ve kodda a_test()önce gelse de burada önce çalışacaktır , çünkü Sırayla 1 2'den önce gelir. JUnit'in temelleri için hepsi bu kadar. Şimdi, birkaç yaygın JUnit Mülakat Sorusunu ele alalım ve yol boyunca JUnit hakkında biraz daha bilgi edinelim! b_test()b_test()a_test()

JUnit Mülakat Soruları (Ek Bilgi)

Burada en popüler JUnit mülakat sorularını topladım. Ekleyecek bir şeyiniz varsa - bunu aşağıdaki yorumlarda yapmaktan çekinmeyin. S: Bir testte otomatik olarak başarısız olmak için test yönteminizde hangi yöntemi arayabilirsiniz? A: fail(“hata açıklaması burada!”); S: Bir Köpek sınıfını test ediyorsunuz; Bir Dog nesnesini test etmek için üzerinde testler yapmadan önce nesneyi başlatmanız gerekir. Böylece, Dog'u başlatmak için bir setUp() işlevi yazarsınız. Tüm testler sırasında bu işlevi yalnızca bir kez çalıştırmak istiyorsunuz. JUnit'in testleri çalıştırmadan önce setUp()'ı çalıştıracağını bilmesi için doğrudan setUp() işlev imzasının üzerine ne koymalısınız? C: @BeforeClass (@BeforeAll in JUnit 5) S:Yukarıda açıklanan setUp() işlevinin işlev imzası ne olmalıdır? A: genel statik boşluk. @BeforeClass (@BeforeAll in JUnit 5) veya @AfterClass (@AfterAll in JUnit 5) ile herhangi bir işlevin statik olması gerekir. S: Köpek sınıfını test etmeyi bitirdiniz. Verileri temizleyen ve her testten sonra bilgileri konsola yazdıran void tearDown() işlevini yazarsınız. Bu işlevin her testten sonra çalışmasını istiyorsunuz. JUnit'in her testi çalıştırdıktan sonra tearDown()'u çalıştıracağını bilmesi için, doğrudan tearDown() işlev imzasının üzerine ne koymalısınız? C: @After (@AfterEach JUnit 5'te)
Yorumlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION