인프런 커뮤니티 질문&답변

버즈님의 프로필 이미지

작성한 질문수

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

통합, 인수 테스트 사전 데이터 세팅 질문

해결된 질문

23.06.18 14:42 작성

·

424

2

안녕하세요 강의 잘 보고 있습니다.

테스트에 대해 파편화 된 지식을 학습자들이 원하는 내용으로 잘 만들어 낸 좋은 강의라고 생각합니다.

 

현재 저희 팀음 통합 테스트 및 인수 테스트를 할 때 미리 쿼리문을 작성해두고 이를 @SqlGroup과 @Sql을 활용하여 데이터를 삽입해주고 있습니다.

이 경우 강의 내에서 말씀하신 것 처럼 스키마 변경이 생길때마다 모든 쿼리를 찾아 수정해야하는 번거로움이 있습니다.

 

하지만 매 케이스마다 세팅을 하기에는 연관된 5개~10개의 테이블에 대한 데이터 수십개를 매번 세팅해줘야 하는 것이 어렵게 느껴집니다.

이때 repository를 계층을 넘어서까지 임포트 해서 사전 데이터 삽입을 해줘야 하는가 궁금하구요.

또한 모든 객체에 Builder를 개방하면 그나마 할만하겠지만 아닌 경우 객체가 제공하는 제한적으로만 생성이 가능할텐데, 리플렉션이라도 써야하는건지 너무 걸리는 경우가 많습니다.

 

다소 두서 없고 여러 질문을 한번에 했지만 제가 어떤 어려움을 겪는지는 전달 되었으리라 생각합니다.

 

답변 2

1

박우빈님의 프로필 이미지
박우빈
지식공유자

2023. 06. 20. 21:54

안녕하세요, 버즈님! :)

말씀해주신 상황에 깊이 공감하며 읽었습니다.
하나씩 나누어서 답변 드려 보겠습니다.

TestFixture 세팅과 관련하여

5~10개 테이블에 대한 데이터를 세팅할 때, 그래서 저는 (강의에서처럼) 모든 객체에 Builder를 열어주는 전략을 사용합니다.
모든 객체에 열어준다는 표현 때문에 거부감이 드실 수도 있겠지만, 다음과 같은 형태입니다.

  • 프로덕션 코드

    • 가능한 정적 팩토리 메서드를 사용하여 메서드명으로 의미를 드러내고, 필요한 경우에 정적 팩토리 메서드가 가지면 좋을 별도의 기능(유효성 검사 등)을 부여한다.

    • 위 방법이 어색하다면 빌더를 사용한다.

  • 테스트 코드

    • 빌더를 사용한다. 단, 빌더를 그대로 사용할 경우 그 길이로 인해 테스트 코드의 가독성을 해칠 수 있으므로 해당 테스트 메서드에 적합한 파라미터만을 드러내는 private 메서드로 추상화하여 사용한다. (강의에서 보여드린 것과 유사한 형태)

또는 프로덕션 코드만을 위한 빌더와, 테스트 코드만을 위한 빌더를 별도로 (builder 이름을 다르게 지정하여) 가져가는 방법도 있지만, 경험 상 오히려 관리 포인트가 늘어나는 느낌이라 추천드리고 싶지는 않습니다 ㅎㅎ

리플렉션 등의 다른 방법을 고민하기 보다는 일종의 Trade-off라 생각하고 팀 내에서 빌더에 관한 컨벤션을 정하는 것이 더 효과적이라고 생각합니다.
빌더를 전부 열어놔도 단점 보다는 장점이 더 많다는 생각이 듭니다 :)

 

인수 테스트

아마 Repository를 계층을 넘어서까지 import 해야 한다는 부분이 언급하신 인수 테스트를 염두에 두셔서 말씀주신 게 아닐까 하는데요.

강의에서 인수 테스트를 다루지는 않았지만, 인수 테스트의 경우는 개념 자체가 통합 테스트와 다릅니다.

애플리케이션 전체를 블랙박스로 두고, 사용자 요청을 거의 그대로 재현해 내어 테스트하는 것이 인수 테스트의 기본 골자이기 때문에, 사전 데이터에 대한 준비도 Repository를 통한 직접 주입이 아니라, 오로지 다른 인수 케이스로만 준비하는 것이 자연스럽습니다.

예를 들어 어떤 사용자가 로그인하는 경우를 테스트한다고 했을 때, 사용자 데이터에 대한 준비는 UserRepository에 직접 User를 저장하기 보다는, 회원가입 인수 테스트를 통해 먼저 사용자의 회원가입이 이루어진 후에, 그 정보를 가지고 로그인 하는 것이 사용자 행위 입장에서 봤을 때 자연스럽다는 의미입니다.

@Test
public void 로그인_테스트() {
    // given
    UserResponse userResponse = UserAcceptanceTest.회원가입_테스트(...);
    
    // when
    // userResponse를 사용한 로그인 인수 테스트

    // then
    // ...
}

강의에서는 테스트 간 의존을 줄여야 한다고 이야기했지만, 인수 테스트는 이렇게 다수의 테스트 케이스가 참여하는 시나리오적 특성을 가지기 때문에 조금 다르게 접근할 필요가 있습니다.

(테스트 후 데이터 클렌징의 경우는 애플리케이션에서 모든 도메인에 대한 삭제 기능을 제공하지 않을 수 있으니 논외로 하겠습니다.)

질문 주신 내용에 대해 이렇게 정리해 볼 수 있을 것 같습니다.
도움이 되셨기를 바랍니다!

감사합니다 :)

0

인프런 AI 인턴님의 프로필 이미지

2023. 06. 20. 14:46

안녕하세요, 인프런 AI 인턴이에요.

통합 테스트 및 인수 테스트에서 데이터 세팅에 대한 고민을 하고 계시는군요. @SqlGroup과 @Sql을 활용하는 방법으로는 스키마 변경이 있을 때마다 모든 쿼리를 수정해야하는 불편함이 있기 때문에 다른 방법을 찾아보셨군요.

repository를 계층을 넘어서까지 임포트 해서 사전 데이터 삽입하는 것도 한 가지 방법이 될 수 있겠습니다. 또는 별도의 데이터 관리 툴을 사용하는 것도 고려해볼 수 있을 것입니다.

객체가 제한적으로 생성 가능하다면 리플렉션을 사용하는 것도 가능하지만, 리플렉션은 성능상의 이슈가 있으므로 사용하는 것이 좋지 않습니다. Builder 패턴 외에도 DataFactory 패턴, Test Data Builder 패턴 등이 있으니 해당 패턴을 적용하여 좀 더 유연한 데이터 생성 방식도 고려해 보시는 것이 좋겠습니다.

조금 더 구체적인 상황에서의 해결 방안을 제시해 드리기 위해서는 더 자세한 정보가 필요할 것 같습니다. 더 많은 정보와 함께 문제 상황을 공유해 주시면 보다 정확한 답변을 제공해 드릴 수 있을 것입니다. 감사합니다.

버즈님의 프로필 이미지

작성한 질문수

질문하기