tech

잘 쓴 테스트 코드란 과연 무엇일까?

과연 내가 잘 쓰고 있는걸까?

테스트 코드는 왜 작성해야 할까?

사람이 직접 테스트를 하게 되면,
놓치는 케이스가 있거나 모든 테스트를 다 하기엔 시간이 많이 소모되고
테스트 코드를 작성하면 회귀 방지가 된다고 한다.

단위 테스트 VS 통합 테스트 VS B2B 테스트

테스트는 여러 단계가 있는데 아래와 같다
단위 테스트
-> 기능에 최소 단위 테스트
-> 이 테스트는 빠르고, 많으면 좋다.

통합 테스트
-> DB, 카프카, 레디스 같이 연동 테스트
-> 필요한 만큼 작성해야 한다.

E2E 테스트 -> (End-to-End)
이 테스트는 핵심 사용자 시나리오만 작성한다고 한다.

그렇다면 왜 이렇게 나누었을까?
아무래도 외부 통신 테스트는 속도 및 통신 장애 문제가 있고
실패가 어디서 되었는 지 DB가 문제인지 내 코드가 문제인지 확인하기 쉽게 분리하여 찾기 쉽게하고 버그를
또 API를 계속 호출하면 데이터 오염이나 비용 문제가 발생할 수 있다.

그러면 테스트 코드는 어떻게 작성해야 좋을까?

given -> when -> then

given, arrange : 필요한 정보 제공
when, act : 어떻게?
then, assert : 결과

그렇다면 우린 실제로 어떻게 써야할까?

@DisplayName("존재하는 로그인 ID를 주면, 해당 유저를 반환한다.")
@Test
void returnsUser_whenUserIdExists() {
    // arrange
    UserModel user = createUser();
    FakeUserRepository userRepository = new FakeUserRepository();
    userRepository.save(user);
    UserService userService = new UserService(userRepository);

    // act
    UserModel result = userService.getUser("user1", "Password1!");

    // assert
    assertThat(result).isSameAs(user);
}

아이디를 주면, 해당 유저를 반환하는 테스트 코드이다.
여기서 먼저 찾을 사용자를 만들어 저장해주고
사용자를 찾아보고 해당 사용자가 맞는 지
마지막에 내가 생각한 결과가 맞는 지 검증하면 이게 테스트 코드다.

이 와중에 또 TDD란게 존재하네

TDD는 테스트 기반 설계라는데 대체 뭔지 알아보자
또 2가지 종류로 나뉘는데 TFD, TLD로 나뉘고 있어 각 내용을 보니 막 어렵진 않았다.

  1. TFD : 테스트 코드 작성 후 설계
  2. TLD : 설계 후 테스트 코드 작성

두 가지 차이는 딱 저렇게라고 하는데 사람들에 물어보니 다들 취향 차이라고 했다.
내가 최근에 회사에서 써봤지만, 확실히 TDD가 있으니 AI가 이상한 짓을 하는 걸 방지할 수 있었다.

또 테스트 코드는 간단하게 끝나지 않더라 아래와 같이 나뉘고 있어 찾아보니

RED(실패하는 테스트) -> GREEN(성공하는 테스트) -> REFACTOR(코드 개선) 

여기서 RED는 실패하는 테스트 코드를 작성한다는데 왜 실패하는 걸 일부로 작성하지라는 의문이 먼저 들었다.
찾아보니까 항상 성공만 하는 테스트도 좋은 테스트라고 할 수 없다고 해서 보니
테스트 코드는 항상 완벽할 수 없다 성공만 한다면 내가 잘 구현했는지 의문을 가져봐야 하고 실패도 의도적으로
작성하여 올바르게 설계가 되었는 지 확인해봐야 할 거 같다.
그러면 여기서 REFACTOR는 뭔지 찾아보니 나중에 6개월 뒤에 다시 봐도
이 코드는 무엇을 테스트하기 위해 존재하며 이렇게 플로우가 흘러가는구나
한눈에 볼 수있게 깔끔하게 정리하여 시간을 아끼는 거 같다.