JUNIT과 친해지기

김주형·2022년 11월 19일
0

자라기

목록 보기
15/22

🙇🏻‍♂️ Reference


테스트 표시하기

@DisplayName("한글") : 테스트 메서드명을 언더바 없이 한글로 작성할 수 있다.
DisplayNameGeneration : 테스트 후 언더바를 제거하여 깔끔하게 볼 수 있다고 한다.

@DisplayName("테스트 인스턴스 생성")
@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
public class Test {
	private Test test;
    
	@BeforeEach
    void setUp() {
    test = new Test();
    
	@Test
    void create_new_test() {
    
    	assertNotNull(test);

중복되는 테스트 코드 개선하기

@ParameterizedTest도 Test객체이므로 @Test와 동시에 사용 시 정상적인 테스트 실행이 어렵다.

중복되는 부분이 많은 여러 개의 테스트 메서드 생성은 관리에도, 가독성에도 좋지 않다. 이것에 대한 대안으로 템플릿으로 빼는 방법, JUNIT5에서 제공하는 @Parameterized 사용이 있다고 한다.

@ParameterizedTest
@ValueSource(strings = {"q", "qwerasdfzxcv", "qq23"})
void createUserException(String name) {
	IllegalArguentException e = assertThrows(IllegalArguentException.class,
    () -> new assertThat(e.getMessage()).isEqualTo(NAME_NOT_MATCH_MESSAGE);

@ParameterizedTest를 사용하면 여러 개의 파라미터에 대한 테스트를 단순화 할 수 있다.

  • @ValueSource : 리터럴 값의 배열에 대한 접근 제공하는 어노테이션
    - 자세한 내용

예시 2

public class Numbers {
	public static boolean isOdd(int number) {
    	return nubmer % 2 != 0;
    }
}


@ParameterizedTest
@ValueSource( ints = {1, 5, 9, -7, 15, 21}) 
@DisplayName("isOdd는 양수일 경우 true를 리턴한다 "
void returnTrueFronIsOdd(int number) {
	assertThat(new Numbers().isOdd(number)).isTrue();
}

입력값에 따라 결과값이 다른 경우

  • @CsvSource(Comma Separated Values) :구분자 기준으로 CSV를 구분해서 읽는다. (구분자는 커스터마이징 가능)
@DisplayName("true, false 값을 같이 리턴")
@ParameterizedTest
@CsvSource(value = {"1:true", "2:true", "3:true", "4:false. "5:false", delimeter = ':')
void set_contains_true_false(int element, boolean expected) {
	assertThat(numbers.contains(element)).isEqualTo(expexted);

파라미터를 테스트 하는 상황

  • 따로 구현 하게 되면 중복 코드 발생
  • 예시 : 숫자 야구 게임의 스트라이크 & 볼에 대한 테스트 코드

@MethodSource : 복잡한 인수들을 파라미터로 전달

  • Object를 가변 인자로 받으므로 다양한 타입을 사용하여 Argument 생성이 가능하다.

예시 : stream 반환하는 static 메서드

  1. @MethodSource안에 static으로 선언한 메서드명을 작성한다.
    메서드명을 올바르게 작성하고, 단축키를 통해 메서드 선언부로 이동할 수 있다. (잘못 선언시 인텔리 제이가 경고)
static Stream(Arguments lottoNumbersAndRank() {
	return Stream.of (
    	Arguments.arguments(new Lotto(givenNumbers(1,2,3,4,5,6)), RANK.FIRST)
        );
}
@ParameterizedTest(name = "로또번호 : {0}, 결과 : {1}")
@MethodSource("lottoNumbersAndRank")
@DisplayName("맞춘 번호에 따라 등수를 반환한다.")
void findRank(Lotto lotto, Rank rank) {
	assertThat(WINNER_LOTTO.findRank(lotto)).isEqualTo(rank);
}

private static List<Number> givenNumbers(int ... numbers) {
	return Arrays.stream(numbes)
    .mapToObj(Number::new)
    .collect(Collecters.toList());
}

static Stream<Arguments> lottoNumbersAndRank() {
	return Stream.of (
    	Arguments.arguments(new Lotto(givenNumbers(1,2,3,4,5,6)), Rank.FRIST),
        Arguments.arguments((new Lotto(givenNumbers(1,2,3,4,5,7) , RANK.SECOND),
        Arguments.arguments(new Lotto(givenNumbers(1,2,8,9,19,11)), Rank.NONE)
        );
}

클래스로 선언하기

ArgumentsProvide 인터페이스를 구현한 클래스를 @ArgumentsSource 어노테이션에 선언해주면 메서드로 선언하지 않고 클래스로 선언하는 방법이 가능해진다고 한다.

public class LottoNumberArgumentsProvide implements ArgumentsProvider {

@Override
publci Stream<? extends Arguments> provideArguments(ExtensionContext context) {
	return Stream.of(
    	Arguments.arguments(new Lotto(givenNumbers(1,2,3,4,5,6)), Rank.FIRST),
        Arguments.arguments(new Lotto(givenNumbers(1,2,3,4,5,7)), Rank.SECOND),
        Arguments.arguments(new Lotto(givenNumbers(1,2,3,4,5,11)), Rank.NONE)
        );
}

private static List<Number> givenNumbers(int...numbers)
	{
	return Arrays.stream(numbers)
    		.mapToObj(Number::new)
            .collect(Collectors.toLists());
 	}
 }
@ParametrizedTest(name = "로또번호 : {0}, 결과 : {1}")
@ArgumentsSource(LottoNumberArgumentsProvider.class)
@DisplayName("맞춘 번호에 따라 등수를 반환한다.)
void findRank(Lotto lotto, Rank rank) {
	assertThat(WINNER_LOTTO.findRank(lotto)).isEqualTo(rank);
}
profile
왔을때보다좋은곳으로

0개의 댓글