본문 바로가기
TIL : Today I learned (or Week)

TIL 230713 : 테스트코드..?

by 우인입니다 2023. 7. 17.

강의를 들으며 느끼는 것 중 하나로 단순히 코드를 짜고 오류가 나지 않게 작동하는 것 이외에 많은 역량이 필요한데, 그 중 하나가 테스트 코드를 작성하고 이를 유지보수 할 수 있는 능력이라고 느끼고 있다. 여러 인터뷰나 자료들을 봤을 때 그렇게 느꼈다. 그리고 그러한 테스트에 대해 JUnit5를 활용한 실습을 살짝 진행했고, 워낙 처음보는 내용들이 많아 정리해보고자 한다.

 


단위테스트, 통합테스트

 

몇 시간을 실행해보지도 않은 채 계속해서 코딩하다가 마침내 실행을 했는데 오류가 난 경험이 있을 것이다.

숨이 턱 막히며 당장 오류를 고쳐야하는데 어디서부터 잘 못 된 건지 찾기 위해 시간을 거슬러 올라가야하는 수고까지 더해진다.

비슷하게 작은 단위에서부터 검증을 한 뒤 작은 기능들의 상호작용까지 검증하고 후반에 서비스 전체에 대한 테스트로 이어지는 것이 전체적으로 효율적이다.

 

그중 초반에 속하는 단위테스트와 통합테스트가 있다.

우선 단위 테스트에 쓰이는 JUnit5의 문법에 대해 알아보며 정리해본다.

 

 

JUnit5

Before-After

각 단위테스트의 전, 후로 개별적 혹은 전체적으로 실행이 되어야할 코드를 세팅해줄 수 있는 어노테이션들이다.

 

@BeforeEach

  • 각각의 테스트 코드가 실행되기 전에 수행되는 메서드를 만들어 줍니다.

 

@AfterEach

  • 각각의 테스트 코드가 실행된 후에 수행되는 메서드를 만들어 줍니다.

 

@BeforeAll

  • 모든 테스트 코드가 수행되기 전에 최초로 수행되는 메서드를 만들어 줍니다.
  • static 메서드로 만들어야합니다.

 

@AfterAll

  • 모든 테스트 코드가 수행된 후 마지막으로 수행되는 메서드를 만들어 줍니다.
  • static 메서드로 만들어야합니다.

 

 

 

테스트 네이밍, 순서, 그룹화

@DisplayName

  • 테스트의 내용을 한눈에 알아볼 수 있게 네이밍 해줄 수 있습니다.
  • 테스트의 수행 내용들을 빠르게 파악할 수 있습니다. 

@Nested

    • 주제 별로 테스트를 그룹지어서 파악하기 좋습니다.

@Order

  • 테스트를 메서드 단위로 순서를 매길 때는 @TestMethodOrder(MethodOrderer.OrderAnnotation.class) 애너테이션 설정을 해야합니다.
  • 그런 다음 원하는 순서에 맞게 메서드에 @Order(2) 애너테이션을 추가하고 () 괄호안에 순서를 입력합니다.

 

 

 

테스트 반복하기

@RepeatedTest

  • @RepeatedTest를 사용하여 해당 테스트 메서드를 반복할 수 있습니다.
  • name 속성을 사용하여 네이밍할 수 있습니다.
  • RepetitionInfo 값을 파라미터로 받아서 현재 반복 횟수와 총 횟수 값을 확인할 수 있습니다.
  •  
@RepeatedTest(value = 5, name = "반복 테스트 {currentRepetition} / {totalRepetitions}")
void repeatTest(RepetitionInfo info) {
    System.out.println("테스트 반복 : " + info.getCurrentRepetition() + " / " + info.getTotalRepetitions());
}

 

 

 @ParameterizedTest

  • @ParameterizedTest를 사용하여 파라미터를 받아 테스트할 수 있는 메서드를 만들 수 있습니다.
  • @ValueSource(ints = {1, 2, 3, 4, 5, 6, 7, 8, 9})를 사용하여 파라미터 값을 전달 할 수 있습니다.
  • 전달되는 파라미터 수 만큼 테스트 메서드가 수행됩니다.
  • int, String 등 여러 타입의 파라미터를 전달할 수 있습니다.
  •  
@DisplayName("파라미터 값 활용하여 테스트 하기")
@ParameterizedTest
@ValueSource(ints = {1, 2, 3, 4, 5, 6, 7, 8, 9})
void parameterTest(int num) {
    System.out.println("5 * num = " + 5 * num);
}

 

 

Assertion

Assertions.assertEquals(expected, actual)

Assertions.assertTrue(boolean)

 

Assertions.assertNotNull(actual)

Assertions.assertThrows(expectedType, executable)

 

Assertion뒤에 오는 여러가지 조건들을 선택하여 예측할 수 있다.

Null이 아니어야 제대로 작동하는 코드의 경우를 예로 들 수 있다.

테스트를 해야할 코드의 결과값이 Null이 아니어야하고 그 결과값을 Assertions.assertNotNull(결과값); 매개변수로 넣어준다.

예상대로 Null아니라면 통과지만 문제가 생겨 Null이 나온다면 검증이 가능하다.

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

의도적으로 5 나누기 0을 연산해 Null이 잘 나오는 지 확인하는 하단의 테스트 코드.

 


우선은 다양한 문법만 익히기에도 상당히 다양하다.

더욱 다양한 정보들은 아래 공식문서에서도 찾아볼 수 있고, 이 기능들을 어떻게 혼합하여 테스트를 잘 해 나갈 지는 곧 작업 효율에 영향을 주고 이는 중요한 역량 중 하나라는 걸 느낄 수 있었다.

 

공식문서 링크 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