강의를 들으며 느끼는 것 중 하나로 단순히 코드를 짜고 오류가 나지 않게 작동하는 것 이외에 많은 역량이 필요한데, 그 중 하나가 테스트 코드를 작성하고 이를 유지보수 할 수 있는 능력이라고 느끼고 있다. 여러 인터뷰나 자료들을 봤을 때 그렇게 느꼈다. 그리고 그러한 테스트에 대해 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
'TIL : Today I learned (or Week)' 카테고리의 다른 글
WIL 230716 : 테스트 코드는 또 뭐냐 (0) | 2023.07.18 |
---|---|
TIL 230714 : MOCK객체란 (사용케이스 추가, given, willReturn) (0) | 2023.07.18 |
TIL 230710 : 다중 JSON 다루기 (JSONObject, JSONArray) (1) | 2023.07.10 |
WIL 230709 : 스프링를 훑어 보며 (0) | 2023.07.09 |
TIL 230707 : 다른 팀의 발표를 보고 (0) | 2023.07.07 |