자바 테스트
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으로 쓰면 상관없어 보이기도 하고.. 사용처를 조금 더 고민해보자.