TIL

+38 단위테스트란? JUnit6

JAVABOZA 2023. 8. 8. 16:23
단위테스트란?
ㅁ버그 발견 시간이 늦어짐에 따라 비용이 기하급수적으로 커지는걸 알 수 있음..
ㅁ 작은 단위로 쪼개서 각 단위가 정확하게 동작하는 지를 검사하는 테스트 기법
ㅁ 빠르게 작성할 수 있고 문제 발생시 어느 부분이 잘 못 되었는지를 빠르고 정확하게 확인할 수 있다는 장점

  • Development : 개발 
  • Unit Tests (단위테스트) : 개발자 테스트
  • QA Testing
    • 블랙박스 테스팅
    • 주로 QA팀이 Production 환경과 유사한 환경에서 테스트
  • Producton : 실 서비스 운영 환경

:: 자바 프로그래밍 언어 용 단위 테스트 프레임워크

 

@BeforeEach

@BeforeEach
void setUp() {
    System.out.println("각각의 테스트 코드가 실행되기 전에 수행");
}

각각의 테스트 코드가 실행되기 전에 수행되는 메서드를 생성

 

@AfterEach

@AfterEach
void tearDown() {
    System.out.println("각각의 테스트 코드가 실행된 후에 수행\n");
}

각각의 테스트 코드가 실행된 후에 수행되는 메서드를 생성

 

@BeforeAll

@BeforeAll
static void beforeAll() {
    System.out.println("모든 테스트 코드가 실행되기 전에 초초로 수행\n");
}

* 모든 테스트 코드가 수행되기전에 최초로 수행되는 메서드를 생성

* static 메서드로 생성해야함

 

@AfterAll

@AfterAll
static void afterAll() {
    System.out.println("모든 테스트 코드가 수행된 후 마지막으로 수행");
}

* 모든 테서트 코드가 수행된 후 마지막으로 수행되는 메서드를 생성

* static 메서드로 생성해야함

 

@DisplayName

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

* 테스트의 내용을 한눈에 알아 볼 수 있게 네이밍 해줄 수 있음

* 테스트의 수행 내용들을 빠르게 파악가능

 

@Nested

* 주제 별로 테스트를 그룹지어서 파악하기 좋음

@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

* 테스트를 메서드 단위로 순서를 매길 때 사용

@TestMethodOrder(MethodOrderer.OrderAnnotation.class) 사용해야함!!

@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");
    }
}

결과


@RepeatedTest

* name 속성을 사용하여 네이밍을 할 수 있음

* @RepeatedTest을 사용해서 해당 테스트 메서드를 반복 할 수 있음

*  RepetitionInfo info 값을 파라미터로 받아서 현재 반복 횟수와 총 횟수 값을 확인 할 수 있음

@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);
}

* @ParameterizedTest를 사용하여 파라미터를 받아 테스트 할수 있는 메서드 생성

* @ValueSource(ints = {1,2,3,4,5,6,7,8,9}) 를 사용하여 파라미터값을 전달 할 수 있음

   ㄴ 전달되는 파라미터  수 만큼 메서드가 수행됨

   ㄴ int, string 등 여러타입의 파라미터를 전달 할 수 있음 

 


Assertions

 

Assertions.assertEquals(expected, actual)

@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);
}

* assertEquals() 메서드는 첫 번째 파라미터에 예상값을 넣고 두 번째 파라미터에 테스트 결과값(실제값)을 넣어준다.

* 예상값과 실제값이 다르면 테스트 실패

* 3번째 파라미터값에 람다식으로 메시지를 넣어두면 테스트 실패 시 해당 메시지 출력

 

 

Assertions.assertTrue(boolean)

@Test
@DisplayName("assertTrue 와 assertFalse")
void test2() {
    assertTrue(calculator.validateNum(9));
    assertFalse(calculator.validateNum(0));
}

* assertTrue() 메서드는 해당 파라미터값이 true인지 확인함

 

 

 

Assertions.assertNotNull(actual)

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

assert NotNull() 메서드는 해당 파라미터 값이 null이 아님을 확인

 

 

Assertions.assertThorws(expectedType, executable)

@Test
@DisplayName("assertThrows")
void test4() {
    IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> calculator.operate(5, "?", 2));
    assertEquals("잘못된 연산자입니다.", exception.getMessage());
}

* assertThrows() 메서드는 첫 번째 파라미터에 예상하는 exception 클래스 타입을 넣고 두 번째 파라미터에 실행코드를 넣으면 됨

* 실행코드의 결과가 예상한 해당 클래스 타입이라면 테스트 성공

 


 

Given - When - Then

Given - When - Then 패턴은 Test Code 스타일을 표현하는 방식을 뜻함

 

Given

  •  테스트 하고자 하는 대상을 실제로 실행하기 전에 테스트에 필요한 값을 미리 선언해둠

When

  • 테스트 하고자하는 대상을 실제로 실행시킴

Then

  • 어떤 특정한 행동 때문에 발생할거라고 예상되는 결과에 대해 예측하고 맞는지 확인
  •  
class CalculatorTest {

    Calculator calculator;

    @BeforeEach
    void setUp() {
        calculator = new Calculator();
    }

    @Test
    @DisplayName("계산기 연산 성공 테스트")
    void test1() {
        // given
        int num1 = 5;
        String op = "/";
        int num2 = 2;

        // when
        Double result = calculator.operate(num1, op, num2);

        // then
        assertNotNull(result);
        assertEquals(2.5, result);
    }

    @Test
    @DisplayName("계산기 연산 실패 테스트 : 분모가 0일 경우")
    void test1_1() {
        // given
        int num1 = 5;
        String op = "/";
        int num2 = 0;

        // when
        Double result = calculator.operate(num1, op, num2);

        // then
        assertNull(result);
    }

    @Test
    @DisplayName("계산기 연산 실패 테스트 : 연산자가 잘못됐을 경우")
    void test1_2() {
        // given
        int num1 = 5;
        String op = "?";
        int num2 = 2;

        // when - then
        IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> calculator.operate(5, "?", 2));
        assertEquals("잘못된 연산자입니다.", exception.getMessage());
    }
}

'TIL' 카테고리의 다른 글

+37 Spring 고어 Entity 삭제  (0) 2023.08.04
+36 영속성 전이  (0) 2023.07.27
+35 Spring 지연로딩  (0) 2023.07.26
+34 Spring N 대 M관계  (0) 2023.07.22
+33 Spring 1대N 연관관계  (0) 2023.07.20