인프런 워밍업 클럽 2기 - BE 클린코드, 테스트코드 스터디 4주차 발자국

인프런 워밍업 클럽 2기 - BE 클린코드, 테스트코드 스터디 4주차 발자국

일주일 간 학습 내용 요약

BDD와 TDD를 활용한 테스트 작성 원칙

  1. 테스트는 문서다

    • 테스트 코드는 프로덕션 기능을 설명하는 문서 역할을 한다.

    • 다양한 테스트 케이스를 통해 프로덕션 코드를 이해하고, 팀 차원의 자산으로 공유할 수 있다.

     

  2. DisplayName을 섬세하게 작성

    • 테스트 이름은 명사 나열보다 문장 형식으로 작성해야 한다.

    • 테스트 행위의 결과까지 명확히 기술하며, 도메인 용어를 사용해 추상화된 내용을 담아야 한다.

    • 메서드 관점이 아닌 도메인 정책 관점에서 기술하는 것이 중요하다.

     

  3. BDD(Behavior Driven Development)

     

    • BDD는 TDD에서 파생된 개발 방법론으로, 함수 단위 테스트보다는 시나리오에 기반한 테스트 케이스에 집중한다.

    • 개발자가 아닌 사람도 이해할 수 있는 수준의 추상화를 권장하며, “Given-When-Then” 구조로 작성된다.

    • Given: 시나리오 진행을 위한 준비 과정.

    • When: 시나리오 행동이 진행되는 단계.

    • Then: 결과를 명시하고 검증하는 단계.

       

     

  4. 테스트 작성 팁

    • 현상을 중점으로 기술하기보다는 도메인 정책에 맞게 테스트를 작성한다.

    • 테스트는 단순한 검증이 아니라 프로덕션 코드의 발전을 돕는 중요한 문서로써 팀의 자산이 된다.

Mocking의 원리

  1. Mock을 마주하는 자세

    • Mocking은 테스트를 할 때 실제 객체 대신에 가짜 객체(Test Double)를 사용하여 객체 간의 상호작용을 검증하는 방법이다.

    • 특히, 외부 시스템과의 상호작용을 모방하여 시스템의 동작을 시뮬레이션한다.

     

  2. Test Double의 종류

    • Dummy: 아무런 기능을 하지 않는 객체.

    • Fake: 실제로는 사용하지 않지만, 간단한 기능을 제공하는 객체(ex. FakeRepository).

    • Stub: 미리 준비된 결과를 제공하는 객체.

    • Spy: Stub처럼 동작하나, 호출된 내용을 기록하여 검증할 수 있는 객체.

    • Mock: 특정 행위에 대한 기대를 명세하고, 그에 따라 동작하도록 만들어진 객체. 상태 검증 대신 행위 검증(Behavior Verification)을 중심으로 한다.

     

  3. Classicist vs. Mockist

    • Classicist: 상태 검증을 중시하는 전통적인 테스트 방식.

    • Mockist: 행위 검증을 중시하는 방식으로, 객체 간의 상호작용을 검증하는 데 집중한다.

     

  4. Spring에서의 Mocking

    • @Mock, @MockBean, @Spy, @SpyBean, @InjectMocks: Spring에서 사용되는 다양한 Mocking 어노테이션과 그 용도.

    • BDDMockito: BDD 스타일로 Mocking을 지원하는 라이브러리.

     

  5. Layered Architecture에서의 Mocking

    • Persistence Layer, Business Layer, Presentation Layer 각각에 대한 Mocking을 적용할 수 있으며, 통합 테스트보다 더 작은 단위의 테스트를 위한 도구로 사용된다.

더 나은 테스트 작성 방법

  1. 테스트 작성 원칙

    • 테스트 하나 당 목적은 하나: 테스트는 명확한 목표를 가지고 하나의 기능만을 검증해야 한다.

    • 완벽한 제어: 테스트에서 모든 상황을 완벽히 제어하고, 외부 의존성 없이 독립적으로 실행될 수 있어야 한다.

    • 테스트 환경의 독립성: 테스트 환경은 독립적으로 설정되어야 하며, 다른 테스트에 영향을 미치지 않아야 한다.

    • 테스트 간 독립성: 각 테스트는 서로 영향을 주지 않도록 독립성을 보장해야 한다.

     

  2. Test Fixture

    • Test Fixture란 테스트를 위해 준비된 고정된 상태의 객체 집합을 의미하며, 테스트가 실행될 때 필요한 환경을 설정해 준다.

    • Fixture 클렌징: 테스트 후 Test Fixture를 적절하게 정리하고 초기화해야 한다.

     

  3. 테스트 수행과 비용

    • 테스트를 수행하는 것도 비용이므로 가능한 한 테스트 환경을 통합하고 효율적으로 구성해야 한다.

     

  4. ParameterizedTest와 DynamicTest

    • @ParameterizedTest: 여러 입력값에 대해 동일한 테스트를 반복할 때 사용한다.

    • @DynamicTest: 동적으로 테스트 케이스를 생성하여 실행할 수 있다.

효과적인 테스트 기반 API 문서화

  1. 학습 테스트

    • 새로운 기능, 라이브러리, 프레임워크 등을 학습하기 위해 작성하는 테스트.

    • 여러 테스트 케이스를 정의하고 검증하는 과정을 통해 해당 기술의 동작과 기능을 더 깊이 이해할 수 있다.

    • 관련 문서를 읽는 것보다 재미있고, 실질적인 학습 방법으로 사용된다.

     

  2. Spring REST Docs

    • API 명세를 자동으로 문서화해주는 도구로, 테스트 코드를 기반으로 API 문서를 생성한다.

    • 문서화된 API 명세는 협업을 원활하게 하며, 테스트가 통과해야 문서가 생성되므로 신뢰도가 높다.

    • 기본적으로 AsciiDoc을 사용하여 문서를 작성한다.

     

  3. REST Docs vs. Swagger

    • Spring REST Docs

      • 테스트를 통과해야 문서가 생성되기 때문에 신뢰도가 높다.

      • 프로덕션 코드에 영향을 주지 않지만 설정이 복잡하고 코드 양이 많다는 단점이 있다.

    • Swagger

      • 설정이 쉽고, 문서에서 바로 API를 호출할 수 있는 기능을 제공한다.

      • 그러나 프로덕션 코드에 영향을 미치고, 테스트와 무관하게 문서가 생성되기 때문에 신뢰도가 떨어질 수 있다.


회고

칭찬하고 싶은 점: 시간이 많이 없었지만 미션과 발자국 모두 기한안에 낼 수 있어서 좋았다.

아쉬웠던 점: 미션 제출 기한에 쫓겨 강의를 서둘러 듣고 제출한 점은 살짝 아쉽다.

보완하고 싶은 점: 배운 내용들을 다시한번 복습해봐야겠다.

드디어 마지막주까지 학습을 마치고 스터디가 끝났다. 4주동안 정말 많은 도움이 됐다. 클린코드와 테스트코드 모두 어느정도 틀과 방향성을 잡았으니 이제 시작이라고 생각한다. 항상 배운 내용들을 생각하고 돌려보며 코드를 작성하는 습관을 들여야겠다.


Day 18 미션


참고강의

박우빈 - Readable Code: 읽기 좋은 코드를 작성하는 사고법

댓글을 작성해보세요.

채널톡 아이콘