단위 테스트란?

bien·2023년 11월 1일
0

우아한테크코스

목록 보기
1/3

이번 주 우테코 프리코스의 목표는 함수를 분리하고, 함수별로 테스트를 작성하는 것이다. 함수를 분리하는 것과 관련해서는 저번주에 느꼈던 객체지향과 관련해서 고민을 해 볼 예정이다. 오늘은 함수별로 테스트를 작성하는 것에 대해 생각해보려고 한다!


단위 테스트에 대해 알아보자!

단위 테스트란?

단위 테스트란, 애플리케이션 안에 있는 개별적인 코드 단위가 의도한 대로 작동하는지 확인하는 행위를 말한다.

더 쉽게 설명하자면, 개별적인 기능이 우리가 의도한대로 작동하는지 확인하는 행위이다.

단위 테스트를 사용하는 이유

Feat. 단위 테스트의 장점은?

  • 원하는 부분만 테스트를 함으로 결과를 빠르게 볼 수 있다.
  • 미리 작성한 단위 테스트를 기반으로 프로덕션 코드의 리펙토링을 안정적으로 할 수 있다.
  • 단위 테스트가 실패하는 지점에서 문제점을 빠르게 찾을 수 있다.

단위 테스트 사용 방법 및 꿀팁

📖 given - when - then 패턴 (테스트 코드 작성의 표현 방식)

1. given

  • 테스트를 위해 준비하는 과정
  • 테스트에 사용하는 값을 정의한다.

2. when

  • 테스트하고 하는 기능을 실행시킨다.

3. then

  • 기능을 실행한 후 결과를 검증한다.

예시

    @Test
    @DisplayName("자동차는 명령을 받은 만큼 이동거리가 증가한다. given/when/then 패턴 적용")
    void car_moves_as_ordered() {
        // given (주어진 값)
        int orderCount = 10;
        Car car = new Car("pobi");
        
        // when (기능 작동)
        car.moveCar(orderCount);
        int distanceResult = car.getDistance();
        
        // then (기능 작동 후 검증)
        assertThat(distanceResult).isEqualTo(orderCount);
    }

📖 @ParameterizedTest (여러개의 값을 테스트할 때)

private void validatePermittedOrderCount(final int orderCount) {
	if (orderCount < 1 || orderCount > 10) {
    	throw new IllegarlArgumentException("이동 시킬 거리는 1 이상 10 이하의 수만 가능합니다.");
    }
}

이 메서드를 테스트 하기 위해 orderCount에 넣고자 하는 값만 변경하여 코드를 중복 작성할 수 있다. 나는 이전에 이처럼 하나의 메서드를 여러 값을 넣어 테스트하기 위해 동일한 코드에 값만 바뀌는 테스트 코드를 작성했었다.

예)

    @Test
    void isInNameRange_전달받은_이름이_5글자_이상인_경우_false_반환() {
        boolean nineLength = Validator.isInNameRange("123456789");
        boolean sixLength = Validator.isInNameRange("123456");

        assertThat(nineLength).isFalse();
        assertThat(sixLength).isFalse();
    }

그러나 이 코드를 @ParameterizedTest@ValueSource를 이용해 더 효과적으로 작성 가능하다!

@ParameterizedTest
@ValueSource(ints = {-1, 0, 11, 12})
@DisplayName("사용자를 이동 시킬 거리가 1 이상 10 이하의 수가 아니면 예외가 발생한다.")
void throws_exception_when_order_count_invalid(int givenOrderCount) {
	// given
    String expectedErrorMessage = "이동 시킬 거리는 1 이상 10 이하의 수만 가능합니다.";
    Car car = new Car();
    
    // when & then
    assertThatThrownBy(() -> car.moveAsOrdered(givenOrderCount))
    		.isInstanceOf(IllegarArgumnetException.class)
            .hasMessageContaining(expectedErrorMessgae);
}            

@ValueSource에는 boolean, String, double 등 여러가지 타입을 사용할 수 있다.
@ValueSource에 작성한 값이 int givenOrderCount에 들어가게 된다.

📖 @Before (메서드 테스트 초기화)

JUnit 테스트를 실행할 때 마다 이 애노테이션이 붙은 메서드를 먼저 실행한다. 따라서, 이 애노테이션을 이용해 모든 메서드 실행 이전에 객체를 초기화할 수 있다.

public class ProfileTest {
	private Profile profile;
    private BooleanQuestion question;
    privte Citeria citeria;

	@Before
    public void create() {
    	profile = new Profile("Bull Hockey, Inc.");
        question = new BooleanQuestion(1, "Got bonuses?");
        criteria = new Criteria();
	}
    
    ...
}

좋은 단위 테스트를 위한 FIRST 규칙

First 원칙이란?

'클린 코드' 책의 저자 Bob Martin이 제시한 규칙으로, 효율적이고 좋은 단위 테스트를 하기 위한 5가지 요소로 이루어진 규칙이다.

[F] Fast

  • 단위 테스트는 빨라야 한다.

테스트를 하는데 과도하게 많은 시간이 소요된다면 잘못된 방향으로 나아가고 있음을 의미할 수 있다. 설계가 깨끗하다면 테스트는 빠르게 유지된다. 느린 테스트를 점검하고, 테스트를 빠르게 유지하자!

[I] Independent

  • 테스트는 독립적으로 동작해야 한다.
  • 이전 테스트에 영향을 받으면 실패 원인을 찾기 어렵다.

테스트 코드는 어떤 순서나 시간에 관계없이 실행할 수 있어야 한다. 각 테스트가 작은 양의 동작에만 집중하면 테스트 코드를 집중적이고 독림적으로 유지하기 쉬워진다. 만약 테스트 메서드가 하나 이상의 이유로 깨진다면 테스트를 분할하는 것도 고려해야 한다.

[R] Repeatable

  • 어떤 상황에서든 예상한 대로 테스트 결과가 나와야 한다.

테스트는 통제 아래에 있어야 하며, 결과가 어떻게 나올지에 대해 단언할 수 있어야 한다. 테스트를 반복실행하더라도, 내가 예상한 결과가 동일하게 나와야만 한다.

[S] Self-Validating

  • 출력 혹은 로그가 아닌 테스트 자체적으로 결과가 나와야한다.

[T] Timely

  • 적시에 테스트를 철저하게 작성 해야한다.

사실 단위테스트는 언제든 작성할 수 있다. 단위 테스트는 좋은 습관이라 양치질 처럼 "이번 한번만"이라며 미루고 싶을 수 있다. 단위 테스트로 코드를 미룰 수록 충치(결함)이 늘어날 수 있다.


Reference

profile
Good Luck!

0개의 댓글