자바 테스트

Junit5 테스트(edit)

백엔드 개발자 2024. 8. 27. 00:02

@Test 어노테이션.
속성 선언 안함.

생명주기
@BeforeAll
@AfterAll

@BeforeEach
@AfterEach

@Disabled
주석처리 없이 테스트하고 싶지 않은 메서드 배제 가능

@DisplayName
어떤 테스트인지 쉽게 표현해준다. 

@RepeatedTest
특정 테스트 반복시키고 싶을때.

@ParameterizedTest
테스트에 여러 다른 매개변수를 대입해가며 반복 실행할 때 사용하는 어노테이션


package org.example;

public class Calculator {

    public int add(int a, int b) {
        return a + b;
    }
}


class CalculatorTest {

    @DisplayName(value = "덧셈 테스트")
    @ParameterizedTest
    @CsvSource({ "1,1,2","2,2,4","3,5,8", "10,-5,5"})
    void testAdd(int a, int b, int expected) {
        Calculator calculator = new Calculator();
        int result = calculator.add(a,b);
        assertEquals(result, expected, "덧셈함수는 올바른 합을 리턴해야 합니다.");
    }
}

 

  • CsvSource를 써서 파라미터 2개 , 원하는 결과값을 세팅해서 테스트를 돌릴 수 있었다. for문없이도 4개의 케이스 테스트를 완료했다.

CsvScource : 다양한 입력값들을 CSV 형식으로 제공해서 여러 테스트 케이스를 한번에 실행할 수 있게 하는 어노테이션.

테스트 메서드의 매개변수 타입에 맞게 콤마로 구분해서 데이터를 세팅한다. 빈값이나 null값도 처리할 수 있다.

 

 

 

@Nested


테스트 클래스 안에서 내부 클래스를 정의해서 테스트 계층화할때 사용하는 어노테이션이라고 한다.

class CalculatorNestTest {

    @Test
    void addition() {
        assertEquals(2, 1 + 1);
    }
    @DisplayName(value = "뺼셈 테스트")
    @Nested
    class SubtractionTests {

        @Test
        void subtractionWithPositiveNumbers() {
            assertEquals(2, 5 - 3);
        }

        @Test
        void subtractionWithNegativeNumbers() {
            assertEquals(-2, -5 - (-3));
        }
    }

    @Nested
    class MultiplicationTests {

        @Test
        void multiplicationWithPositiveNumbers() {
            assertEquals(6, 2 * 3);
        }

        @Test
        void multiplicationWithZero() {
            assertEquals(0, 0 * 5);
        }
    }
}

  • 테스트 코드의 계층화를 통해 가독성을 개선할 수 있다.  다양한 상태나 컨텍스트에서 동일한 기능 테스트할때 유용하다.
  • Nested 내부에서만 BeforeEach등으로 초기화할 수 있어서, 테스트별 초기상태를 변경시킬 수 있다. 독립적으로 테스트 환경을 만들 수 있다.
  • BDD 스타일 테스트 작성방식과 잘맞고, given-when-then 구조를 명확히 할 수 있다고 한다.

 

BDD 스타일 

  • given-when-then 구조로 시나리오를 정의해서 비즈니스 요구사항과 테스트코드 간극 줄이는 개발방법론
  • 비즈니스 언어(요구사항)와 개발 언어를 일치시키려는 시도이다.
  • given: 어떤 상황이 주어졌을때(상태 설정)
  • when: 어떤 동작이 발생했을때(실행)
  • then: 기대되는 결과가 나와야 한다.(검증)

@Nested가 BDD 스타일을 더 잘 소화할 수 있는 이유

 

  • Nested는 계층구조를 만들 수 있다. 그래서 given when then을 더 명확하게 보여줄 수 있다.
  • BDD의 스토리와 시나리오를 체계적으로 표현하는데 큰 도움이 된다.

BDD 스타일로 적어본 @Nested 테스트

    @Nested
    @DisplayName("Given")
    class AddTests {
        private int a;
        private int b;
   
        @BeforeEach
        void setUp() {
            a = 5;
            b = 3;
        }
        
        @Test
        void addTests() {
            assertEquals(3, calculator.add(a,b));
        }
        @Test
        void addTests2() {
            int a = 3;
            int b = 4;
            assertEquals(7, calculator.add(a,b));
        }
    }

 

 

 

Assertions


  • 테스트 케이스의 수행 결과를 판별하는 메서드이다.
  • 모든 Junit Jupiter Assertions는 static 메서드라고 한다.

 

assertAll(executables...)

  • 매개변수로 받는 모든 테스트 코드를 한 번에 실행한다.
  • 오류가 나도 끝까지 실행후 한번에 모아서 출력한다고 한다.

 

@Test
void addition() {

    assertAll(
            () -> assertEquals(4, 1 + 1,"1fail"),
            () -> assertEquals(2, 1 + 1,"2fail"),
            () -> assertEquals(3, 1 + 1,"3fail")
            );

}

 

  • 실제로 테스트를 해보니 중간에 1개만 맞췄음에도 다 테스트를 돌려보고 2개가 fail난걸 확인 가능하다.
  • 그런데, 저렇게 하면 중간에 어떤 테스트가 실패했는지는 콘솔을 봐야지 정확하게 알 수 있을텐데, 가독성 면에서는 @nested로 다 찢어서 작성하는게 낫지 않나라는 생각도 든다. 동일한 조건일때 한번에 할 수 있는 장점이 있을 순 있지만, 그것도 @Nested에 given when then으로 쓰면 상관없어 보이기도 하고.. 사용처를 조금 더 고민해보자.

 

 

 

 

https://www.youtube.com/watch?v=EwI3E9Natcw