워밍업 클럽 4기 백엔드 - 4주차 발자국

워밍업 클럽 4기 백엔드 - 4주차 발자국

강의 내용

Practical Testing: 실용적인 테스트 가이드

  • Test Double

    • 테스트를 위해 실제 객체나 모듈 대신 사용하는 가짜 객체/모듈

    • Dummy, Fake, Stub, Spy, Mock

  • Mockito, BDDMockito

    • Mock 프레임워크

    • @Mock, @MockBean, @Spy, @SpyBean, @InjectMocks 등 mocking을 편리하게 할 수 있도록 돕는 프레임워크

    • BDDMockito는 기존의 Mockito가 제공하는 API가 BDD style에 맞지 않는다는 문제를 해결하기 위해 Mockito를 wrapping 해서 BDD 스타일로 테스트를 작성할 수 있도록 해준다.

       

  • Test Fixture

    • 테스트를 위한 데이터 준비 시 테스트의 독립성이 보장되고, 테스트의 내용을 이해하는데 문제가 없도록 해야 함

    • Given 절에 해당하는 Test Fixture가 숨어버리는 정보의 파편화로 인해 테스트의 내용을 한 번에 이해할 수 없게 되는 경우를 주의

       

  • Parameterized Test, Dynamic Test

    • 하나의 테스트는 하나의 테스트 케이스만 검증

    • 테스트에서 쓰이는 반복문, 분기문은 곧 테스트가 여러 케이스를 검증하고자 한다는 방증

    • 하나의 테스트 케이스에 속하는데 여러 값을 넣어보며 대해 검증하고자 한다면, @ParameterizedTest 사용

    • 시나리오에 따라 공유 자원의 상태를 추적하며 순차적, 단계적으로 테스트를 하고 싶다면 @DynamicTest를 이용

  • 테스트 환경 통합

    • 테스트도 비용이며, 테스트의 실행 시간을 늘리는 가장 큰 요인 중 하나는 Spring 서버를 띄우는데 소요되는 시간

    • 테스트 환경을 통합하면 서버를 다시 띄우는 횟수가 줄어들어 테스트 비용 절감 가능

    • DataJpaTest를 사용해 Jpa 관련 Bean만 생성하는 것보다 SpringBootTest를 이용해 테스트 환경을 재구성 횟수를 줄이는 편이 더 효율적일 수 있음

  • private 메소드의 테스트, 테스트에서만 필요한 메소드

    • private 메소드에 대한 테스트는 기본적으로 public 메소드를 테스트하는 과정에서 함께 이루어지며, private 메소드에 대한 테스트는 불필요하다.

    • private 메소드 테스트가 필요하다고 판단하는 경우는 객체 분리가 필요한 시점은 아닌지 고민해봐야 하는 상황

    • 테스트에서만 필요한 메소드를 정의해 사용할 수 있다.

    • 다만 trade-off가 존재하며, 객체가 마땅히 할 법한 행위이며 미래에 프로덕션 코드에서 사용될 가능성이 있는 콛으인 경우에만 사용해야 한다.

  • 학습 테스트

    • 테스트 코드를 작성하면서 새로운 기술, 라이브러리 등에 대해 익히는 것은 효과적인 학습법이다.

  • Spring REST Docs

    • 테스트 코드를 이용해 API 문서를 작성할 수 있는 자동화 도구

    • 테스트 코드를 통과해야 문서가 만들어지기 때문에 Swagger에 비해 신뢰도가 높으며, 프로덕션 코드에 비침투적이라는 장점이 있다.

       

 

회고

드디어 완강을 했다. '드디어'라는 표현이 무색하게도, 이제부터가 시작이라는 생각이 든다. 강의를 다 들었고 코드도 착실하게 따라서 쳤지만, 더 많은 고민과 연습이 필요할 것 같다. 어떻게 하면 더 읽기 좋고, 객체지향적인 코드를 짤 수 있을지, 어떻게 해야 좋은 테스트를 작성할 수 있을지 시간을 들여 고민하고, 경험을 쌓아서 체화할 필요가 있다.

이전 강의도 마찬가지였지만, 이번주 강의 내용은 특히 더 많은 도움이 되었다. 워낙 익숙하지 않아 어렵게 느껴지는 Mocking에 조금이나마 익숙해질 수 있었고, 테스트를 처음 접하는 입장에서 생겼던 의문 중 상당수가 자연스럽게 해소되었다. 워밍업 클럽 스터디에 참여하면서 중간 중간 미션도 수행하고, 다른 러너 분들의 코드도 보고, 중간 점검 시간도 갖고, 발자국을 작성하며 복습도 하게 되어 강의를 따라가는 과정이 훨씬 수월했던 것 같다. 스터디 기간 동안 학습한 내용을 조금씩 실무에 응용해보면서 연습을 해봤는데, 이제 스터디가 끝났으니 개인적으로 프로젝트를 진행하면서 배운 것을 녹여내어 내 것으로 만들어볼 생각이다.

 

미션

Day 16

Day 16 미션은 Layered Architecture에서의 레이어 별 특징과 테스트 작성 방법에 대해 나만의 언어로 정리하는 미션이었다. 단순히 강의를 들으며 정리했던 내용을 복습하는 것을 넘어서, 강의에서 다룬 레이어별 테스트 방법을 떠올리며 왜 그런 방식을 소개해 주셨는지 고민하면서 미션을 수행했다. 일종의 best practice를 제시해 주신 것으로 생각하지만, 테스트 작성 경험이 없던 터라 강의에서 배운 방식 외에도 직접 다양한 방식을 시도해보고 싶은 마음이 들었다.

 

Day 18

Day 18 미션은 Mockito에서 Mock 객체 생성 및 주입을 위한 어노테이션들의 차이점을 정리하고, 예시로 주어진 테스트 코드 작업 항목을 @BeforeEach, given절, when절에 배치해보는 미션이었다. 공통적으로 필요한 데이터는 @BeforeEach 안에, 테스트 하고자 하는 핵심 기능은 when절에 작성하고, 나머지는 given절에 작성했다.

2차 중간 점검에서 Day 18 미션의 핵심은 중복 제거가 아니라 '도메인'이었다는 피드백을 받았다. 사용자와 게시물을 생성하는 코드는 '댓글'이라는 테스트 대상 도메인이 아닌 부수적 요소이므로 setUp()에 작성하고, 핵심이 되는 '댓글' 관련 로직만 각 테스트 메소드에 작성할 수 있다는 관점이었다. 미션 수행 당시에 가장 고민했던 사용자 2의 데이터 생성 코드는 setUp에 넣든 3번 테스트에 남기든 크게 중요하지 않았다. 미션을 수행할 때는 테스트 1, 테스트 2에서 사용되지 않을 데이터이니 setUp으로 빼지 않기로 결정했는데, setUp에 해당 코드가 위치하더라도 테스트의 독립성이 깨지는 등의 문제가 발생하지는 않으니, 오히려 댓글이라는 핵심 도메인에 확실히 집중할 수 있겠다는 생각이 들었다. 테스트가 필요한 이유, 테스트의 목적에 대해 다시 한 번 생각해보게 하는 답변이었다. 결국 코드라는 것은 목적을 위한 수단이고, 테스트 코드 역시 마찬가지다. 강의 후반부에서도 다루었듯이, 학습 테스트나 Spring REST Docs 등 테스트는 다양한 목적으로 사용할 수 있다. 항상 목적을 잊지 않고, 그 목적에 맞게 코드를 작성하도록 주의해야겠다는 생각이 들었다.

댓글을 작성해보세요.

채널톡 아이콘