본문 바로가기

250925(목) 단위테스트

@6uiw2025. 9. 25. 23:25
학습 목표

1. JUnit의 기능들 알아보기 - 테스트 클래스 활용법
2. Assertions 알아보기 

 

 

1. JUnit의 기능들 알아보기 - 테스트 클래스 활용법

 

📌Before / After

@BeforeEach
테스트 클래스에서 command + N > SetupMethod
각각의 테스트가 실행되기 전에 실행되는 메서드

@AfterEach
테스트 클래스에서 command + N > TearDownMethod
각각의 테스트 코드가 실행된 후에 실행되는 메서드 

@BeforeAll
테스트 클래스에서 command + N > BeforClass Method
모든 테스트 코드가 실행되기 전에 최초로 수행

@AfterAll
테스트 클래스에서 command + N > AfterClass Method
모든 테스트 코드개 수행된 후 마지막으로 수행

 

 

package com.sparta.junit5practice;

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;

public class BeforeAfterTest {
		//테스트 클래스에서 command + N  > SetupMethod
    @BeforeEach //각각의 테스트가 실행되기 전에 실행되는 메서드
    void setUp() {
        System.out.println("각각의 테스트 코드가 실행되기 전에 수행");
    }
		//테스트 클래스에서 command + N  > SetupMethod
    @AfterEach
    void tearDown() {
        System.out.println("각각의 테스트 코드가 실행된 후에 실행\n");
    }
		//테스트 클래스에서 command + N  > BeforClass Method
    @BeforeAll
    static void beforeAll() {
        System.out.println("모든 테스트 코드가 실행되기 전에 최초로 수행\n");
    }
    
    //테스트 클래스에서 command + N  > AfterClass Method
    @AfterAll
    static void afterAll() {
        System.out.println("모든 테스트 코드개 수행된 후 마지막으로 수행");
    }
    
    
    @Test
    void test1() {
        System.out.println("테스트 코드 작성 1");
    }

    @Test
    void test2() {
        System.out.println("테스트 코드 작성2");
    }
}

 

 

 

 

📌Nested() :주제별로 그룹지어서 테스트하고 싶을 때

package com.sparta.junit5practice;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

public class CustromTest {

    @Test
    @DisplayName("테스트의 내용을 한눈에 알아볼 수 있게 네이밍해줄 때")
    void test1() {
        System.out.println("테스트 내용 빠르게 파악");
    }

    @Nested
    @DisplayName("주제 별로 테스트를 그룹지어서 파악하기 좋습니다.")
    class Test1 {
        @Test
        @DisplayName("Test1 - test1()")
        void test1() {
            System.out.println("Test1.test1");
        }

        @Test
        @DisplayName("Test1 - test2()")
        void test2() {
            System.out.println("Test1.test2");
        }
    }

    @Nested
    @DisplayName("Test2 다른 주제")
    class Test2 {
        @Test
        @DisplayName("Test2 - test1()")
        void test1() {
            System.out.println("Test2.test1");
        }

        @Test
        @DisplayName("Test2 - test2()")
        void test2() {
            System.out.println("Test2.test2");
        }
    }
}

 

 

 

📌@Order()

코드를 차례대로 입력해도 메서드를 선언한 순서대로 실행되지 않는다.

따라서 테스트를 메서드 단위로 순서를 매겨야 할때 @Order 사용

package com.sparta.junit5practice;

import org.junit.jupiter.api.*;

public class CustromTest {

    @Test
    @DisplayName("테스트의 내용을 한눈에 알아볼 수 있게 네이밍해줄 때")
    void test1() {
        System.out.println("테스트 내용 빠르게 파악");
    }

    @Nested
    @DisplayName("주제 별로 테스트를 그룹지어서 파악하기 좋습니다.")
    @TestMethodOrder(MethodOrderer.OrderAnnotation.class)
    class Test1 {

        @Order(1)
        @Test
        @DisplayName("Test1 클래스")
        void test() {
            System.out.println("\nTest1 클래스");
        }

        @Order(3)
        @Test
        @DisplayName("Test1 - test1()")
        void test1() {
            System.out.println("Test1.test1");
        }

        @Order(2)
        @Test
        @DisplayName("Test1 - test2()")
        void test2() {
            System.out.println("Test1.test2");
        }
    }

    @Nested
    @DisplayName("Test2 다른 주제")
    class Test2 {
        @Test
        @DisplayName("Test2 - test1()")
        void test1() {
            System.out.println("Test2.test1");
        }

        @Test
        @DisplayName("Test2 - test2()")
        void test2() {
            System.out.println("Test2.test2");
        }
    }
}

 

 

📌RepeatTest

package com.sparta.junit5practice;

import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.RepetitionInfo;

public class RepeatTest {
    //메서드를 반복해서 수행 , value : 몇번 돌릴지
    // getCurrentRepetition = 몇번 돌아갔는지 / getTotalRepetitions = 총 몇번 돌릴지
    @RepeatedTest(value = 5, name = "반복 테스트 {currentRepetition} / {totalRepetitions}")
    void repeatTest(RepetitionInfo info) {
        System.out.println("테스트 반복 : " + info.getCurrentRepetition() + " / " + info.getTotalRepetitions());
    }
}

 

 

 

📌 ParameterizedTest

    //전달되는 파라미터 수만큼 테스트메서드가 수행됨 
    @DisplayName("파라미터 값 활용하여 테스트 하기")
    @ParameterizedTest
    @ValueSource(ints = {1, 2, 3, 4, 5, 6, 7, 8, 9}) //전달해주고 싶은 파라미터 값 
    void parameterTest(int num) {
        System.out.println("5 * num = " + 5 * num);
    }

 

 

 

 

2. Assertions

기능 검증하기

 

 

검증할 클래스 생성

Calculator - 계산기 기능

 

package com.sparta.junit5practice;

public class Calculator {
    public Double operate(double num1, String op, double num2) {
        switch (op) {
            case "*":
                return num1 * num2;
            case "/":
                if (validateNum(num2)) {
                    return num1 / num2;
                } else {
                    return null;
                }
            case "+":
                return num1 + num2;
            case "-":
                return num1 - num2;
            default:
                throw new IllegalArgumentException("잘못된 연산자입니다.");
        }
    }

    public boolean validateNum(double num) {
        if (num == 0) {
            return false;
        } else {
            return true;
        }
    }
}

 

Assertions 를 이용한 검증

 

📌 assertEquals / assertNotEquals

package com.sparta.junit5practice;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

public class AssertionTest {

    Calculator calculator;

    @BeforeEach
    void setUp() { //테스트 실행 전에 객체를 하나씩 생성하게끔 설정
        calculator = new Calculator();
    }

    @Test
    @DisplayName("assertEquals")
    void test1() { //성공
        Double result = calculator.operate(5, "/", 2);
        assertEquals(2.5, result);
    }

    @Test
    @DisplayName("assertEquals - Supplier")
    void test1_1() {
        Double result = calculator.operate(5, "/", 0);
        // 테스트 실패 시 메시지 출력 (new Supplier<String>())
        assertEquals(2.5, result, () -> "연산자 혹은 분모가 0이 아닌지 확인해보세요!");
    }

    @Test
    @DisplayName("assertNotEquals")
    void test1_2() {
        Double result = calculator.operate(5, "/", 0);
        assertNotEquals(2.5, result); //예측이 틀려야 통과 
    }
}

 

두번째 테스트 -> 실패 시 동작을 알아보자

    @Test
    @DisplayName("assertEquals - Supplier")
    void test1_1() {
        Double result = calculator.operate(5, "/", 0);
        // 테스트 실패 시 메시지 출력 (new Supplier<String>())
        assertEquals(2.5, result, () -> "연산자 혹은 분모가 0이 아닌지 확인해보세요!");
    }

 

 

 

 

 

📌 assertTrue / assertFalse

    //boolean 값을 검증하고 싶을 때
    @Test
    @DisplayName("assertTrue 와 assertFalse")
    void test2() {
        assertTrue(calculator.validateNum(9)); //true를 반환하는지
        assertFalse(calculator.validateNum(0)); //false를 반환하는지
    }

 

 

 

📌 assertNull, assertNotNull

    //null 여부 체크 
    @Test
    @DisplayName("assertNotNull 과 assertNull")
    void test3() {
        Double result1 = calculator.operate(5, "/", 2);
        assertNotNull(result1);
        Double result2 = calculator.operate(5, "/", 0);
        assertNull(result2);
    }

 

 

📌 assertThrows

    //exception 테스트 
    @Test
    @DisplayName("assertThrows") // (예상하는 클래스 타입 , 실제 테스트)
    void test4() {
        IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> calculator.operate(5, "?", 2));
        assertEquals("잘못된 연산자입니다.", exception.getMessage()); //예측하는 메시지와 실제 메시지가 일치하는지 체크 
    }

 

 


 

오늘의 코멘트

내가 구현한 기능이 원활하게 작동하기 위해선 테스트가 필요하다. 코드가 로컬에선 잘 작동해도, 실제 서비스를 제공하다보면 어떤 오류가 발생할지 모르기 때문이다. junit에서 많은 테스트 기능들을 제공하는 것은 알았지만, 한번 더 공부하면서 내가 생각하는 것 이상의 디테일한 기능들이 존재한다는 것을 알게 되었다.
모든 기능을 다 공부하고 써볼 수는 없으므로, 개발을 하며 직접 테스트를 진행하면서 필요한 기능들을 찾아보고 공부해야 겠다. 

 

6uiw
@6uiw :: LOG.INFO("MING's DEVLOG")

개발을 하면서 공부한 기록을 남깁니다

목차