[단위 테스트]given,when,then 사용

Lee Yongin·2024년 2월 23일
0

배경지식

목록 보기
3/3
post-thumbnail

단위 테스트를 작성해보자 라고 마음먹고 어떻게 써야하는지 검색했을 때 정말 많이 봤던 패턴이 given-when-then이다.
더 근본있는(?) 정보를 위해 클린코드에서 '단위테스트' 장을 보게되었다.
이 포스트는 도메인에 특화된 DSL 테스트언어 및 이중표현 등의 내용은 차치하고, 가장 쓸모있는 관련 내용만 내 코드와 함께 버무린 글이다.

테스트가 제공하는 것

유연성

유지보수성

재사용성

깨끗한 테스트 코드란 가독성이 있어야 함

바로 가독성이다. 명료하고 단순하고 표현을 풍부하게 하면 가독성이 좋아진다(말은 쉽지)

How

  • 중복되는 코드는 최소한으로
  • 자질구례한 사항은 표현력을 떨어뜨린다

예시 (build-operate-check 패턴)

내가 테스트코드를 처음 써본 경험은 우테코 프리코스였다. 과거를 반면교사 삼고 싶었지만 간단한 과제였기에 생각보다 간결하게 작성한 듯하다...
DiscountCalculator 객체를 만들고 -> calculateWeekendDiscount 메소드를 실행해 할인가를 도출하고 -> 할인가가 예상가와 일치하는지 확인
일반화하자면
테스트 자료를 만들고 -> 메서드를 실행해서 테스트 자료를 조작하고 -> 조작한 결과가 올바른지 확인하는 과정이다.

BUILD-OPERATE-CHECK 패턴 이라고 한다!는 걸 이제 알았다

class DiscountCalculatorTest {
@ParameterizedTest
    @MethodSource("generateWeekendDiscountArgument")
    fun `주말 할인가격이 일치하는지 확인 테스트`(date: Int, menus: List<Menu>, expected: Int) {
        val discountCalculator = DiscountCalculator(date, menus)
        val result = discountCalculator.calculateWeekendDiscount()
  		assertThat(result).isEqualTo(expected)
    }
}

의미를 알면 눈길이 문자열을 따라 움직이며 결과를 재빨리 판단한다

이 말은 테스트 코드 뿐만 아니라 클린코드의 정신 그 자체인 문장같았다.
클린 코드에 있던 코드예제와 유사하게 쓰자면 아래와 같다.

@Test
public void turnOnCoolerAndBlowerIfTooHot() throws Exception{
	tooHot();
    assertEquals("CoolerAndBlower", hw.getState());
}
public void turnOnHeaterAndBlowerIfTooCold() throws Exception{
	tooHot();
    assertEquals("HeaterAndBlower", hw.getState());
}

반면교사

밑의 테스트코드는 내가 썼던 것이다.

차를 달려!
랩보여줘!
그리고 결과를 확인ㅎ...이게 뭐지?

@Test
    fun `1번의 이동기회마다 모든 자동차의 경주 결과를 보여주는지 확인`() {
        carLane.runCars()
        carLane.showLap()

        Assertions.assertThat(output.contains("a :\nb :\nc :\n"))
    }

저 알 수 없는 "a :\nb :\nc :\n"가 문제이다. 문제가 생각이 잘 안나지만, lap을 돌은 결과를
a:1
b:2
c:3
이렇게 보여주려고 한 거라면, 문자열 "a :\nb :\nc :\n"를 lapResultForm라는 변수로 저장해서
아래와 같이 썻을 것 같다.

@Test
    fun `1번의 이동기회마다 모든 자동차의 경주 결과를 보여주는지 확인`() {
        carLane.runCars()
        carLane.showLap()

        Assertions.assertThat(output.contains(lapResultForm))
    }

테스트 당 assert는 하나!

JUnit으로 테스트 코드를 짤 때는 함수마다 assert문을 단 하나만 사용하라는 학파가 있다고 한다. 확실히 결론이 하나니까 이해가 쉽긴하다. 하지만 모든 테스트케이스에

그래도 항상 결론이 하나일 수는 없어서 assert를 여러개 쓰게 되는데~

그걸 given-when-then 패턴이 해결해주게 되었다.

테스트 당 개념 하나!

테스트 당 개념 하나만 두면 자연스럽게 잡다한 개념을 연속으로 테스트하는 함수는 작성하지 않게 되기 때문이다.

깨끗한 테스트의 5가지 규칙

F.I.R.S.T

Fast : 빠르게

자주돌려야 하니까!

Independent: 독립적으로

각 테스트는 서로 의존하면 안 된다

Repeatable: 반복가능하게

어떤 환경에서도 반복가능

Self-Validating: 자가검증하는

성공 아니면 실패다. 절대 로그 파일을 읽게 해선 안됨

Timely: 적시에

테스트하려는 실제코드 구현 직전에 한다

profile
f1을 좋아하는...🏆 f1처럼 빠르고 정확한 걸 좋아하는 안드로이드 개발자

0개의 댓글