본문 바로가기
백엔드(Back End)/Spring

[TIL]20230726 - 테스트 코드 작성

by tjsdn9803 2023. 7. 28.

테스트의 단계

다음 그래프는 개발단계, 단위테스트 단계, QA테스트 단계, 서비스 단계에서 버그가 발생할 시 들어가는 비용을 나타낸 것이다.

비용을 줄이기 위해 최대한 빨리 버그를 발견하는것이 좋기 떄문에 테스트 코드를 작성하여 프로그램의 버그를 사전에 발견하여 비용의 증가를 방지할 수 있다.

단위 테스트는 작으 ㄴ단위로 쪼개서 각 단위가 정확하게 동작하는지를 검사하는 테스트 기법으로 빠르게 작성할 수 있고 문제 발생 시 어느 부분이 잘못 되었는지를 빠르고 정확하게 확인할 수 있다는 장점이 있다.

https://junit.org/junit5/docs/current/user-guide/#writing-tests-annotations

 

JUnit 5 User Guide

Although the JUnit Jupiter programming model and extension model do not support JUnit 4 features such as Rules and Runners natively, it is not expected that source code maintainers will need to update all of their existing tests, test extensions, and custo

junit.org

JUnit5는 자바 프로그래밍 언어에서 사용하는 단위 테스트 프레임워크이다.

JUnit은 프로젝트 생성시 아무런 의존성을 추가하지 않아도 build.gradle에 가면 spring-boot-starter와 함께 spring-boot-starter-test가 포함되어 생성된다.

testImplementation 'org.springframework.boot:spring-boot-starter-test'
Implementation 'org.springframework.boot:spring-boot-starter'

테스트 코드를 생성하는 방법은 직접 생성할 수도 있지만 테스트 코드를 작성하고 싶은 클래스에서 오른쪽 마우스 클릭을 통해 Generate-test...를 통해 생성하면 Main디렉토리와 같은 위치에 클래스명 + Test의 이름으로 테스트 클래스가 생성된다.

class PostServiceTest {

}

Before - After

@BeforeEach는 각각의 테스트 코드가 실행되기 전에 수행되게 하는 어노테이션이다.

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

@AfterEach는 각각의 테스트 코드가 실행된 후에 수행되게 하는 어노테이션이다.

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

@BeforeAll는 모든 테스트가 수행되기 전에 최초로 한번 수행되게 하는 어노테이션이다.

(주의! static으로 만들어야함)

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

@AfterAll 모든 테스트가 수행된 후에 수행되게 하는 어노테이션이다.

(주의! static으로 만들어야함)

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

@DisplayName는 테스트의 이름을 정하는 어노테이션이다. 테스트 시 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");
    }
}

 


Assertions.assertEquals(expected, actual)

  • assertEquals() 메서드는 첫 번째 파라미터에 예상값을 넣고 두 번째 파라미터에 테스트 결과값(실제값)을 넣어줍니다.
  • 예상값과 실제값이 다르면 테스트가 실패합니다.
  • 3번째 파라미터 값에 람다식으로 메시지를 넣어두면 테스트 실패 시 해당 메시지가 출력됩니다. (new Supplier<String>())

Assertions.assertTrue(boolean)

  • assertTrue() 메서드는 해당 파라미터 값이 true인지 확인합니다.

Assertions.assertNotNull(actual)

  • assertNotNull() 메서드는 해당 파라미터 값이 null이 아님을 확인합니다.

Assertions.assertThrows(expectedType, executable)

  • assertThrows() 메서드는 첫 번째 파라미터에 예상하는 Exception 클래스 타입을 넣고 두 번째 파라미터에 실행 코드를 넣으면 됩니다.
  • 실행 코드의 결과가 예상한 해당 클래스 타입이라면 테스트에 성공합니다.

Given - When - Then

Given - When - Then패턴은 필수 작성은 아니지만 테스트 코드의 컨벤션이라 볼수 있다.

Given

  • 테스트 하고자하는 대상을 실제로 실행하기 전에 테스트에 필요한 값(상태)을 미리 선언해 둡니다.

When

  • 테스트 하고자하는 대상을 실제로 실행 시킵니다.

Then

  • 어떤 특정한 행동(테스트 대상 실행) 때문에 발생할거라고 예상되는 결과에 대해 예측하고 맞는지 확인합니다.

'백엔드(Back End) > Spring' 카테고리의 다른 글

[TIL]20230728 - 팔로우 기능 구현  (1) 2023.07.31
[TIL]20230727 - Mockito  (0) 2023.07.28
[TIL]20230725 - JaCoCo  (0) 2023.07.28
[TIL]20230718 - Spring Boot 이미지 업로드 구현  (0) 2023.07.18
[TIL]20230713 - RefreshToken  (0) 2023.07.14