JUnit
Java tabanlı geliştirilen kodları test etmek için kullanılan JUnit nedir, kurulumu, kullanımı ve özellikleri ile ilgili bilgiler yer alıyor.
JUnit nedir?
Java tabanlı kodların test edilmesi için kullanılan bir Unit Test – Birim Testi kütüphanesidir.
Test nedir?
Belirlenen girişlere göre beklenen bir sonuç vermesini denemek için kullanılan geliştirme-deneme yöntemidir.
Unit Test nedir?
Unit test veya birim testi programları oluşturulan alt parçaların-birimlerin test edilmesidir.
NOT: Java gibi OOP tabanlı programlama dillerinde bu parçalar metot olarak adlandırılır.
Neden kullanılır?
Programlama dilleri temel olarak giriş-input alarak çıktı-output üretir.
Girişlerin ve çıkışların kaynağı farklı olsa da aynı girişlerin aynı sonuç vermesi beklenir.
Bu beklentiyi doğrulamak için her bir giriş ve çıkış değerinin kontrolünün tek-tek yapılması gerekir.
Her bir giriş ve çıkış değerinin tek-tek yapılması yazılım geliştirme sürecini uzatır.
JUnit gibi araçlar test işlemlerini kolaylaştırır ve çeşitli ek özellikler sunarak bu süreyi kısaltır.
NOT: Unit test yazılan kodların hatalarını bulmak için kullanılmaz.
JUnit ayrıca TDD veya test odaklı geliştirme yapmayı sağlar.
TDD yazılım geliştirme öncesi yapılan planın test edilerek kodun yazılmasıdır.
Aşağıda bazı test yöntemleri yer almaktadır.
- Unit Testing
- Integration Testing
- Smoke Testing
- Stress Testing
- Security Testing
- Smoke Testing
- Load Testing
JUnit kurulumu
JUnit 5 ile birlikte JUnit Platform, JUnit Jupiter, JUnit Vintage gibi alt parçalara ayrılarak platform haline gelmiştir.
Maven projesi oluşturalım.
mvn archetype:generate \
-DgroupId=com.yusufsezer \
-DartifactId=JUnitApp \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DinteractiveMode=false
JUnit kütüphanesini pom.xml dosyasına ekleyelim.
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.2</version>
<scope>test</scope>
</dependency>
JUnit testelerini Maven ile çalıştırmak için maven-surefire-plugin eklentisini ekleyelim.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.2.5</version>
</plugin>
</plugins>
</build>
Örnek sınıf ve metot aşağıda yer almaktadır.
public class App {
public static void main(String[] args) {
System.out.println("Hello JUnit!");
}
public boolean isPositive(Integer number) {
return number > 0;
}
}
JUnit kullanımı
JUnit kütüphanesinin kullanımı annotations kullanımından ibarettir.
Annotations hakkında detaylı bilgi için Java Annotations yazıma bakmalısın.
public class AppTest {
@Test
public void pozitif_deger_dogru() {
var number = 1453;
var app = new App();
boolean expResult = true;
boolean result = app.isPositive(number);
Assertions.assertEquals(expResult, result);
}
@Test
public void negatif_deger_yanlis() {
var number = -1453;
var app = new App();
boolean expResult = false;
boolean result = app.isPositive(number);
Assertions.assertEquals(expResult, result);
}
}
Testi çalıştırmak için aşağıdaki komutu komut yorumlayıcısına yazmak yeterli olacaktır.
mvn test
Örnekte @Test ifadesi ile metodun test olduğu belirtilmiş Assertions sınıfında yer alan assertEquals metodu ile test işlemi yapılmıştır.
NOT: Netbeans, Eclipse ve Intellij gibi IDE özellikleri ile hızlıca oluşturma, yazma ve çalıştırma işlemi yapılabilir.
Assertion method
JUnit5 ile yapılan test işlemleri için Assertions sınıfında yer alan overload edilmiş statik assert*** metotları kullanılır.
Bazı assert metotları şunlardır;
- assertEquals
- assertNotEquals
- assertArrayEquals
- assertIterableEquals
- assertNull
- assertNotNull
- assertLinesMatch
- assertNotSame
- assertSame
- assertTimeout
- assertTimeoutPreemptively
- assertTrue
- assertFalse
- assertThrows
- *fail
NOT: fail metodu test işleminin doğrudan başarısız olduğunu ifade etmek için kullanılır.
Örneğin; Sık kullanılan assertEquals metodu iki değerin eşit olup olmadığını test etmek için kullanılır.
JUnit Test LifeCycle
Servlet, JSF, JPA, Spring vb birçok Java bileşeninde yer alan LifeCyle veya yaşam döngüsü JUnit’te de yer alır.
Test başlangıcında @BeforeAll ile belirtilen statik metotlar çalıştırılır.
Her bir test öncesi @BeforeEach, test sonrası @AfterEach ile belirtilen metotlar çalışır.
Test bitişinde @AfterAll ile belirtilen statik metotlar çalıştırılır.
public class AppTest {
@BeforeAll
public static void beforeAll() {
System.out.println("@BeforeAll");
}
@BeforeEach
public void beforeEach() {
System.out.println("@BeforeEach");
}
@Test
public void pozitif_deger_dogru() {
System.out.println("@Test");
var number = 1453;
var app = new App();
boolean expResult = true;
boolean result = app.isPositive(number);
Assertions.assertEquals(expResult, result);
}
@Test
public void negatif_deger_yanlis() {
System.out.println("@Test");
var number = -1453;
var app = new App();
boolean expResult = false;
boolean result = app.isPositive(number);
Assertions.assertEquals(expResult, result);
}
@AfterEach
public void afterEach() {
System.out.println("@AfterEach");
}
@AfterAll
public static void afterAll() {
System.out.println("@AfterAll");
}
}
Yaşam döngülerinin kullanım amacı test işlemi öncesi nesnelerin oluşturulması test işlemi sonrası kaynakların serbest bırakılmasıdır.
Önceki örnekte yer alan nesne oluşturma JUnit yaşam döngüsü ile aşağıdaki gibi yapılır.
public class AppTest {
App app;
@BeforeEach
public void beforeEach() {
app = new App();
}
@Test
public void pozitif_deger_dogru() {
System.out.println("@Test");
var number = 1453;
boolean expResult = true;
boolean result = app.isPositive(number);
Assertions.assertEquals(expResult, result);
}
@Test
public void negatif_deger_yanlis() {
System.out.println("@Test");
var number = -1453;
boolean expResult = false;
boolean result = app.isPositive(number);
Assertions.assertEquals(expResult, result);
}
}
Varsayılan olarak JUnit her bir metot öncesi yaşam döngüsünü TestInstance.Lifecycle.PER_METHOD ile çalıştırır.
Yaşam döngüsünün çalışmasını değiştirmek için test sınıfına @TestInstance(TestInstance.Lifecycle.PER_CLASS) eklemek yeterli olacaktır.
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class AppTest {
Integer myNumber = 0;
@Test
public void test1() {
myNumber += 1;
System.out.println(myNumber);
Assertions.assertEquals(1, myNumber);
}
@Test
public void test2() {
myNumber += 1;
System.out.println(myNumber);
Assertions.assertEquals(2, myNumber);
}
}
Test çalıştırıldığında her metot için yeniden yaşam döngüsü çalışmayacaktır.
@DisplayName – Test metodunun IDE ortamında görünen ismini değiştirir.
@Test
@DisplayName("Pozitif değer")
public void test1() {...}
NOT: Sonucun görünmesi için IDE ayarının yapılması gerekebilir.
@Disabled – Testi devre dışı bırakmak için kullanılır.
@Test
@Disabled
public void bir_test() {
// ...
}
Koşula bağlı test
JUnit içerisindeki @EnabledOnOs, @EnabledOnJre, @EnabledIf, @EnabledIfSystemProperty ve @EnabledIfEnvironmentVariable sayesinde bir koşula bağlı metodun çalışması sağlanır.
@Test
@EnabledOnOs(OS.MAC)
public void bir_test() {
// ...
}
Test Mac tabanlı işletim sisteminde çalışacaktır.
Assumtations
Bazı testler için bazı kaynakların hazır olması gerekebilir.
Assumtations ile kaynağın test edilerek çalıştığının belirlenmesi aksi halde testin çalışmaması sağlanabilir.
@Test
public void bir_test() {
boolean siteye_erisildi = false; // erişim kontrolü yapılıyor
Assumptions.assumeTrue(siteye_erisildi);
// test işlemi
}
Test işlemini başlaması için siteye_erisildi değerinin true olması gerekir.
AssertAll – Testleri gruplamak ve çalıştırmak için kullanılır.
@Test
public void bir_test() {
Assertions.assertAll(
() -> Assertions.assertEquals(0, 0),
() -> Assertions.assertEquals(1, 2),
() -> Assertions.assertEquals(3, 3)
);
}
@Nested – Testleri bir alt sınıf içerisinde gruplamak için kullanılır.
public class AppTest {
@Nested
@DisplayName("Alt test")
class AltTest {
@Test
public void pozitif_deger_dogru() {
var number = 1453;
var app = new App();
boolean expResult = true;
boolean result = app.isPositive(number);
Assertions.assertEquals(expResult, result);
}
@Test
public void negatif_deger_yanlis() {
var number = -1453;
var app = new App();
boolean expResult = false;
boolean result = app.isPositive(number);
Assertions.assertEquals(expResult, result);
}
}
// Diğer testler
}
@RepeatedTest – Parametre kadar test çalıştırmak için kullanılır.
public class AppTest {
@RepeatedTest(5)
public void bir_test() {
System.out.println("Yusuf SEZER");
}
}
Toplam test sayısı, hangi test adımında olduğu bilgisine RepetitionInfo ile erişilir.
public class AppTest {
@RepeatedTest(5)
public void bir_test(RepetitionInfo repetitionInfo) {
int current = repetitionInfo.getCurrentRepetition();
int total = repetitionInfo.getTotalRepetitions();
System.out.printf("Toplam: %d Tekrar: %d %n", total, current);
}
}
@Tag – Testleri gruplamak, etiketlemek için kullanılır.
public class AppTest {
@Test
@Tag("dev")
public void dev_test() {
System.out.println("dev");
}
@Test
@Tag("prod")
public void prod_test() {
System.out.println("prod");
}
}
Maven ile sadece DEV etiketine sahip testleri çalıştırmak için aşağıdaki komut kullanılır.
mvn test -Dgroups=DEV
TestInfo – Test hakkında bilgi almak için kullanılır.
public class AppTest {
@Test
@Tag("dev")
@DisplayName("Örnek bir test")
public void bir_test(TestInfo testInfo) {
System.out.println(testInfo.getDisplayName());
testInfo.getTags().forEach(System.out::println);
testInfo.getTestClass().ifPresent(System.out::println);
testInfo.getTestMethod().ifPresent(System.out::println);
}
}
JUnit ile test yazarken Netbeans, Eclipse, IntelliJ gibi IDE ortamının kullanımı faydalı olacaktır.
Java Derslerine buradan ulaşabilirsiniz.
Hayırlı günler dilerim.