|
1 | 1 | --- |
2 | 2 | layout: post |
3 | | -title: " 테스트에 대한 전략과 고찰 " |
| 3 | +title: "테스트에 대한 전략과 고찰" |
4 | 4 | categories: [ GoodCode ] |
5 | 5 | author: devFancy |
6 | 6 | --- |
@@ -60,7 +60,7 @@ author: devFancy |
60 | 60 |
|
61 | 61 | 이러한 경험 덕분에, 저는 회사와 팀의 상황에 맞춰 '안정적인 서비스를 만든다'를 목표로 한 걸음씩 나아가는 태도를 갖게 되었습니다. |
62 | 62 |
|
63 | | -## 가치 있는 테스트 코드를 작성하기 위한 전략 |
| 63 | +## 테스트 코드를 작성하기 위한 전략 |
64 | 64 |
|
65 | 65 | 무작정 테스트를 작성하기보다 "좋은 테스트란 무엇인가?"를 고민하며 저만의 기준을 세우게 되었습니다. |
66 | 66 |
|
@@ -88,7 +88,7 @@ author: devFancy |
88 | 88 | > |
89 | 89 | > "작성 가치를 현명하게 고려하면 가치 있는 20%의 테스트로 80% 이상의 신뢰성을 얻을 수 있습니다." |
90 | 90 |
|
91 | | -이 문장을 보면서 무작정 테스트 커버리지(수치)를 높이는 것보다 **핵심 비즈니스 로직(가치)을 지키는 20%에 집중**하는 것이 효율적이라는 것을 알게되었습니다. |
| 91 | +이 문장을 보면서 무작정 테스트 커버리지(수치)를 높이는 것보다 **핵심 비즈니스 로직(가치)을 지키는 20%에 집중**하는 것이 효율적이라는 것을 알게 되었습니다. |
92 | 92 |
|
93 | 93 | 또한, 테스트를 작성하다 보면 **실용성**도 고려해야 했습니다. |
94 | 94 | 테스트 시나리오가 많아질수록 각 계층별로 작성해야 할 양과 겹치는 부분이 많아지게 됩니다. |
@@ -212,14 +212,14 @@ class TitleTest { |
212 | 212 | 그래서 저는 빠른 피드백과 검증의 정확성 사이에서 균형을 맞추기 위해 통합 테스트 계층에서 시나리오 테스트를 구현하는 방법을 선택했습니다. |
213 | 213 | (추후 E2E 레벨의 인수 테스트 경험이 쌓이면 이 포스팅에 내용을 보강할 예정입니다.) |
214 | 214 |
|
215 | | -* `통합 테스트`란 서로 다른 모듈(Controller, Service, Repository 등)이 상호작용하며 제대로 동작하는지 검증하는 테스트입니다. 데이터베이스와 같은 외부 의존성을 포함하여 시스템의 내부 흐름을 검증합니다. |
| 215 | +* `통합 테스트`란 서로 다른 계층이 상호작용하며 제대로 동작하는지 검증하는 테스트입니다. 데이터베이스와 같은 외부 의존성을 포함하여 시스템의 내부 흐름을 검증합니다. |
216 | 216 |
|
217 | 217 | 사용자 시나리오는 복잡한 비즈니스 로직이 포함된 단일 API일 수도 있고, 회원가입부터 주문까지 이어지는 여러 과정일 수도 있습니다. |
218 | 218 |
|
219 | 219 | 단순 조회 기능과 달리 실제 비즈니스 가치를 검증해야 하므로, 테스트를 작성하다 보면 입력 데이터의 복잡성이나 환경 격리 등 현실적인 난관에 부딪히게 됩니다. |
220 | 220 | 이를 해결한 경험을 아래에 공유합니다. |
221 | 221 |
|
222 | | -### Given 절에서 반복되는 부분을 Fixtures로 활용하기 |
| 222 | +### Given 절에서 반복되는 부분을 Fixture 로 활용하기 |
223 | 223 |
|
224 | 224 | 서비스 규모가 커지고 연관된 객체가 많아질수록 테스트의 Given 절(준비 단계)이 비대해지는 문제가 발생합니다. |
225 | 225 |
|
@@ -297,11 +297,11 @@ class PostServiceTest { |
297 | 297 |
|
298 | 298 | 위 코드처럼 Given 절을 재활용하지 않으면 테스트를 작성할수록 동일한 셋업 코드가 중복되고 이는 테스트를 작성하는 핵심 관심사의 양보다 많아져서 나중에는 테스트의 핵심 의도를 파악하기가 어려워지게 됩니다. |
299 | 299 |
|
300 | | -이러한 문제를 해결하기 위해, 각 테스트마다 반복되는 객체 생성 로직을 별도의 헬퍼 클래스로 분리하는 Test Fixtures 방식을 도입했습니다. |
| 300 | +이러한 문제를 해결하기 위해, 각 테스트마다 반복되는 객체 생성 로직을 별도의 헬퍼 클래스로 분리하는 Test Fixture 방식을 도입했습니다. |
301 | 301 |
|
302 | 302 | #### Fixture 적용 후: 핵심 로직에 집중 |
303 | 303 |
|
304 | | -`Test Fixtures`란 테스트를 위해 원하는 상태로 고정시킨 일련의 객체나 데이터를 의미합니다. (흔히 '고정물'이라고도 부릅니다.) |
| 304 | +`Test Fixture`란 테스트를 위해 원하는 상태로 고정시킨 일련의 객체나 데이터를 의미합니다. (흔히 '고정물'이라고도 부릅니다.) |
305 | 305 |
|
306 | 306 | 예를 들어, 게시글 관련 통합 테스트를 작성할 때 Given 절에서 반복되는 셋업을 아래와 같이 Fixtures 클래스를 작성해볼 수 있습니다. (이 외에 회원, 프로필 클래스도 마찬가지로 Fixtures 클래스를 작성합니다.) |
307 | 307 |
|
@@ -533,7 +533,7 @@ class CouponServiceImplTest { |
533 | 533 |
|
534 | 534 | 결국 유지보수성과 편의성 사이의 트레이드오프라고 생각합니다. 그래서 저는 아래와 같은 기준을 세워 적용하고 있습니다. |
535 | 535 |
|
536 | | -* 일반적인 도메인 검증시에는 코드 기반의 Fixtures를 사용합니다. |
| 536 | +* 일반적인 도메인 검증시에는 코드 기반의 Fixture를 사용합니다. |
537 | 537 |
|
538 | 538 | * 그리고 테스트 독립성을 확보하기 위해 가급적 전역 데이터를 사용하지 않습니다. |
539 | 539 |
|
@@ -625,7 +625,7 @@ public class DatabaseCleaner { |
625 | 625 | `@SpringBootTest`를 사용하면 스프링 컨텍스트(서버)가 로딩되는데, 설정(Configuration)이 달라질 때마다 컨텍스트가 새로 띄워지게 됩니다. |
626 | 626 | 이는 테스트가 많아질수록 전체 빌드 시간을 기하급수적으로 늘리는 원인이 됩니다. |
627 | 627 |
|
628 | | -이를 방지하기 위해, 저는 모든 통합 테스트가 상속받아 사용할 수 있는 상위 추상 클래스인 `IntegrationTestSupport` 추상 클래스를 구현했습니다. |
| 628 | +이를 방지하기 위해, 저는 모든 통합 테스트가 상속받아 사용할 수 있는 상위 추상 클래스인 `IntegrationTestSupport`를 구현했습니다. |
629 | 629 |
|
630 | 630 | ```java |
631 | 631 | @Import(JpaAuditingConfig.class) |
|
0 commit comments