한 눈에 들어오는 Test Fixture 를 구성하기 위한 조언
GIven 절에서 중복되는 테스트 픽스처를 제거하려고 하지 말고 문서 용도로 활용 할 것
@ActiveProfiles("test")
@SpringBootTest
class Test {
@BeforeAll
void beforeAll() {
// ...
}
@BeforeEach
void setUp() {
// testFixture...
}
}
위 코드에서 beforeAll, beforeEach 와 같은 테스트 라이프사이클에 의해 정의가 되는 메서드에서 공통적으로 사용하는 테스트 픽스처를 구성했다고 해보자.
그럼 매 테스트 간 Given 절에 불필요한 중복을 줄이고 더 깔끔하게 보일 수 있으니 테스트 코드가 좋은 문서가 되었다고 쉽게 착각할 수 있다.
크게 오해하고 있는 것은 중복을 제거하는 것이 미덕이 되지 않는 상황도 분명 존재한다는 것인데, 이렇게 한 곳에서 테스트 픽스처를 관리하면 테스트 환경의 독립성을 보장하자가 어긋나게 된다.
결국 또 하나의 전지전능한 공유변수를 만들어내는 행위이니, 되도록이면 테스트 픽스처를 한 곳에서 관리하려 하지말고 각 테스트 간 Given 절에서 다루도록 하는게 좋다 아무리 중복이 발생하더라도.
그럼에도 불구하고 beforeEach 와 같은 메서드 내에서 테스트 픽스처를 관리 해야 하는 경우
테스트 코드를 작성하기 전 항상 질문하기
수정해도 모든 테스트에 영향을 주지 않는가
각 테스트 입장에서 봤을 때, 아예 몰라도 테스트 내용을 이해하는 데에 문제가 없는가
만약, 주문 내역에 관한 테스트를 작성할 때 주문 내역을 만들기 위해 상품이 객체 관계에 의해 무조건 생성 되어야 한다고한다.
그리고 주문 내역은 상품에 대한 정보를 알지도 못할 뿐더러, 객체간 관계로 인해 필요만 할 뿐 메서드 내부에서 사용되는 곳이 없다.
이렇게 의존성을 띄지만 직접적인 연관을 짓지 않는 경우는 테스트 픽스처를 setUp 에서 사용해도 무방하다.
즉, 공유 자원으로 인해 상태를 변경하는 메서드가 난무하는 테스트 환경에서 서로가 서로를 강결합하게 구성하지 말자.
data.sql 에서 DML을 통해 given 데이터를 모두 만들지말자

Given 절에서 흔히 Repository 를 이용해 데이터를 생성하는 작업을 미리 구성해둔다. 이렇게 작성해둔 테스트 코드는 해당 메서드가 어떤 데이터로 인해 수행 되었다 라는 내용을 쉽게 알 수 있다.
하지만, 모든 Given 절에서 그 길고 긴 테스트 데이터를 만들어내기 귀찮고, 가독성을 떨어트린다고 생각이 들어 data.sql 에서 생성한다고 가정해보자.
이 경우는 이제 엄청난 소프트웨어 내에서 숨바꼭질이 시작된 것이다.
찾았다고 한들 테스트 코드와 data.sql 을 같이 확인 해야하고, 정보가 모두 파편화 되어있어서 스스로 정보를 통합하는 불필요한 과정이 추가된다.
그렇다면 프로젝트 규모가 커졌을 때는 어떨까? 굉장히 많은 데이터를 생성해야하고, 또 다른 파일이 생겨나고, 스키마 변경에 대해 대응 해야하는 이상한 관리포인트가 늘어나게 된다.
테스트의 빌더 함수의 시그니처는 꼭 필요하는 정보만 받을 것
@DisplayName("신규 상품을 등록하는 경우, 상품번호는 가장 최근 상품의 상품번호에서 1 증가한 값이다.")
@Test
void createProductWhenProductsIsExists() {
// given
Product product1 = createProduct("001", HANDMADE, SELLING, "아메리카노", 4000);
// ...
}
private Product createProduct(String productNumber, ProductType productType,
ProductSellingStatus productSellingStatus, String name, int price) {
return Product.builder()
.productNumber(productNumber)
.type(productType)
.sellingStatus(productSellingStatus)
.name(name)
.price(price)
.build();
}
테스트 환경을 구성할 때 굉장히 지저분한 픽스처 관리를 빌더 함수를 이용해 깔끔하게 만들 수 있다.
여기서 주의할 점은 빌더 함수에게 넘겨줘야 할 파라미터는 꼭 필요한 정보만 주는 것이다.
상품에 이름이 같아도 상관이 없다거나, 상품의 상태에 영향을 받지 않는다거나 등.. 속성 값에 영향을 받지 않는다면 빌더 함수 내부에서 하드코딩 하여 값을 지정하고, 테스트 구성을 위해 변하는 값들만 받도록 구성하는 것이 좋다.
결론적으로 테스트에 필요한 필드만 명시하여 구성하는 방법을 사용하는 건 각자 다른 테스트 클래스에서 이 빌더 함수가 공통적으로 쓰일 수 없다는 것을 의미하고, 각자 상황에 맞는 테스트 코드를 만들어낼 수 있다는 뜻도 속한다.
이 내용은 바로 다음에 다룰 "중복을 줄이기 위해 빌더 함수를 공통으로 분리 하지 말자" 라는 내용을 보면 이해가 쉬울 것이다.
중복을 줄이기 위해 빌더 함수를 공통으로 분리 하지 말자
테스트 환경을 구성하는 빌더 함수에 파라미터를 제한하여 사용하다보면, 테스트 클래스마다 중복으로 생성하는 경우가 꽤 비일비재하다.
그렇다고 해서 "중복을 제거하는 것이 미덕이야" 라며 또 공통으로 관리하기 시작하면 문제가 발생하기 쉽다.
그 중 가장 대표적인 것은, 여러 개발자가 협업할 때 각자 필요한 데이터의 형태가 다를 수 있다. 하지만, 공통으로 생성 된 빌더 함수를 직접적으로 수정하면 누군가에게 영향을 줄테니 새로운 파라미터를 갖는 함수가 나타날 것이다.
만약 실무에서 적용한 Entity 의 속성 값이 30개, 40개가 된다고 했을 때 40개의 경우의 수를 전부 따진 빌더 함수를 만드는 샘이다.
결국 파라미터만 다른 무수히 많은 빌더들이 생겨나는 것을 방지하기 위해서 테스트 클래스 내에 필요한 필드만 구성한 빌더 함수를 만들도록 노력해야한다.
Last updated