티스토리 뷰

Java

[Java] Junit Parameterized Test

snail voyager 2024. 12. 4. 23:25
728x90
반응형

@Parameterized 

JUnit의 @ParameterizedTest 어노테이션은 동일한 테스트를 다양한 매개변수로 여러 번 실행할 수 있게 해줍니다. 

이를 통해 같은 테스트 케이스에 대해 다양한 입력 값을 테스트할 수 있어 테스트의 포괄성과 효율성을 높일 수 있습니다.

https://www.baeldung.com/parameterized-tests-junit-5 

public class ParameterizedTestExample {
    
    @ParameterizedTest
    @ValueSource(strings = {"racecar", "radar", "able was I ere I saw elba"})
    void testPalindrome(String candidate) {
        assertTrue(isPalindrome(candidate));
    }

    private boolean isPalindrome(String candidate) {
        String sanitized = candidate.replaceAll("\\s+", "").toLowerCase();
        return new StringBuilder(sanitized).reverse().toString().equals(sanitized);
    }
}

@ValueSource

기본 데이터 타입, 문자열, 클래스 지원.

null 은 허용하지 않는다.

  • short (with the shorts attribute)
  • byte (bytes attribute)
  • int (ints attribute)
  • long (longs attribute)
  • float (floats attribute)
  • double (doubles attribute)
  • char (chars attribute)
  • java.lang.String (strings attribute)
  • java.lang.Class (classes attribute)
@ParameterizedTest
@ValueSource(ints = {1, 2, 3, 4, 5})
void testWithIntValueSource(int argument) {
    assertTrue(argument > 0 && argument < 6);
}

@CsvSource

여러 인수를 한 번에 전달할 수 있는 편리한 방법 제공.

@ParameterizedTest
@CsvSource({
    "test, TEST",
    "tEst, TEST",
    "Java, JAVA"
})
void testWithCsvSource(String input, String expected) {
    assertEquals(expected, input.toUpperCase());
}

@CsvFileSource

CSV 파일을 입력으로 사용.

@ParameterizedTest
@CsvFileSource(resources = "/test-data.csv", numLinesToSkip = 1)
void testWithCsvFileSource(String input, String expected) {
    assertEquals(expected, input.toUpperCase());
}

@MethodSource

스트림, Iterable, 또는 배열 형태의 인수를 반환하는 팩토리 메서드 참조.

@ParameterizedTest
@MethodSource("stringProvider")
void testWithMethodSource(String argument) {
    assertNotNull(argument);
}

static Stream<String> stringProvider() {
    return Stream.of("foo", "bar");
}

@EnumSource

지정된 Enum의 상수를 사용.

enum TimeUnit { DAYS, HOURS, MINUTES, SECONDS }

@ParameterizedTest
@EnumSource(TimeUnit.class)
void testWithEnumSource(TimeUnit timeUnit) {
    assertNotNull(timeUnit);
}

사용자 정의 인수 변환

public class CustomConverterTest {

    @ParameterizedTest
    @ValueSource(strings = "2020-01-01")
    void testWithCustomConverter(@ConvertWith(LocalDateConverter.class) LocalDate date) {
        assertEquals(LocalDate.of(2020, 1, 1), date);
    }

    static class LocalDateConverter extends SimpleArgumentConverter {
        @Override
        protected Object convert(Object source, Class<?> targetType) {
            assertEquals(LocalDate.class, targetType, "Can only convert to LocalDate");
            return LocalDate.parse(source.toString());
        }
    }
}

@ConvertWith

매개변수화된 테스트를 지원하는 애노테이션으로, 사용자 정의 ArgumentConverter를 통해

입력값을 테스트 메서드가 필요로 하는 특정 타입으로 변환할 수 있도록 해줍니다.

 

  • 재사용 가능: 변환 로직을 분리해 여러 테스트에서 재사용 가능
  • 유연성 제공: 기본 제공되는 변환을 넘어서, 커스텀 타입으로 변환할 수 있는 유연성을 제공
  • 매개변수화된 테스트 강화: 단순 입력값(String)을 복잡한 객체로 변환해 실제 테스트 데이터에 더 가깝게 사용할 수 있음

 

import org.junit.jupiter.params.converter.ArgumentConverter;
import org.junit.jupiter.params.converter.ArgumentConversionException;

public class StringToPersonConverter implements ArgumentConverter {

    @Override
    public Object convert(Object source, Class<?> targetType) throws ArgumentConversionException {
        if (!(source instanceof String)) {
            throw new ArgumentConversionException("Source must be a String");
        }
        String[] parts = ((String) source).split(",");
        if (parts.length != 2) {
            throw new ArgumentConversionException("String must be in 'name,age' format");
        }
        return new Person(parts[0].trim(), Integer.parseInt(parts[1].trim()));
    }
}

public class PersonTest {

    @ParameterizedTest
    @ValueSource(strings = {"Alice,30", "Bob,25"})
    void testPersonConversion(@ConvertWith(StringToPersonConverter.class) Person person) {
        // 테스트 수행
        System.out.println(person);
        assertEquals(2, person.getName().length());  // 예제용 검증
    }
}

org.junit.jupiter.params.provider.Arguments

JUnit에서 매개변수화된 테스트에 여러 인수를 제공하는 데 사용됩니다. 

Arguments는 Stream<Arguments> 형태로 매개변수를 제공하는데 유용합니다. 

이를 통해 복잡한 데이터 셋을 테스트할 수 있습니다.

Arguments를 사용하여 JUnit의 매개변수화된 테스트를 작성하면 다양한 입력 데이터로 동일한 테스트 로직을 실행할 수 있어 테스트의 효율성과 신뢰성을 크게 향상시킬 수 있습니다.

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

import java.util.stream.Stream;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class CalculatorTest {

    @ParameterizedTest
    @MethodSource("provideAdditionArguments")
    void testAddition(int a, int b, int expectedSum) {
        assertEquals(expectedSum, a + b);
    }

    static Stream<Arguments> provideAdditionArguments() {
        return Stream.of(
            Arguments.of(1, 1, 2),
            Arguments.of(2, 3, 5),
            Arguments.of(3, 5, 8),
            Arguments.of(10, 20, 30)
        );
    }
}

 

728x90
반응형

'Java' 카테고리의 다른 글

[Java] record  (0) 2025.01.12
[Java] Lombok @UtilityClass  (0) 2025.01.12
[Java] 비트 연산  (0) 2024.10.13
[Java] 단위테스트 Spock Framework  (0) 2024.06.09
[Java] Mockito BDD (Behavior Driven Development)  (0) 2024.06.02
반응형
300x250