TestFixtures로 테스트 의존성 관리하기

왔다 정보리·2025년 10월 9일
1
post-thumbnail

테스트 코드를 작성하다보면 중복 코드가 많이 발생한다. 특히 멀티 모듈 환경에서는 test 폴더의 코드를 다른 모듈에서 사용할 수 없기 때문에 모듈마다 같은 코드를 반복해서 작성해야 했다. 이렇게 되면 이후에 유지보수도 어렵게 된다. 같은 내용을 모듈마다 작성하다 보니 다른 방법이 없을지 찾아보게 되었고 TestFixtures라는 것을 알게 되었다.


TestFixtures


TestFixtures

Gradle에서 제공하는 기능으로, 테스트 관련 코드를 다른 모듈에서 재사용할 수 있다. 예를 들어 공통으로 사용하는 Builder 클래스나 Helper 클래스를 한 곳에서 관리할 수 있다. 또한 상위 모듈의 테스트 전용 의존성까지 함께 전파되어 각 모듈에서 의존성을 중복으로 추가하지 않아도 된다. 따라서 TestFixtures를 사용하면 테스트 코드 관련 중복 코드를 최소화할 수 있고 유지보수에 용이하다.

TestFixtures의 장점

  1. 모든 모듈이 동일한 테스트 설정을 공유하여 일관된 테스트 환경을 제공한다.
  2. 테스트 관련 공통 설정을 한 곳에서 관리할 수 있어 중복 코드를 제거할 수 있다.
  3. 테스트 설정이 변경되거나 새로운 모듈을 추가할 때 testFixtures 폴더만 수정하면 모든 곳에 반영된다. 따라서 유지보수가 용이하다.

TestFixtures 구조

project-root
├── core
│   ├── src/main           # 일반 코드
│   ├── src/test           # core 모듈 테스트
│   └── src/testFixtures   # 🎯 공유할 테스트 설정
│       └── java/com/example/core
│           ├── config
│           │   └── TestContainerConfig.java
│           └── test
│               └── AcceptanceTestConfig.java
├── 하위 모듈 1              # testFixtures 의존성 사용
└── 하위 모듈 2              # testFixtures 의존성 사용

TestFixtures를 사용하면 위와 같은 멀티 모듈 환경에서 상위 모듈(core)의 src/testFixtures 디렉토리에 있는 코드를 하위 모듈에서 사용할 수 있게 된다.

TestFixtures 적용하는 법


1. Core 모듈 의존성 설정

plugins {
    id 'java-test-fixtures'  // TestFixtures 활성화
}

dependencies {
    testFixturesApi 'org.springframework.boot:spring-boot-starter-test'
    testFixturesImplementation 'org.testcontainers:testcontainers'
    testFixturesImplementation 'org.testcontainers:junit-jupiter'
    testFixturesImplementation 'org.testcontainers:mysql'
    testFixturesImplementation 'org.testcontainers:jdbc'
    testFixturesApi 'io.rest-assured:rest-assured'
}
  • java-test-fixtures : TestFixtures 기능을 활성화한다
  • testFixturesApi : 하위 모듈에 테스트 관련 의존성을 전파한다
  • testFixturesImplementation : 하위 모듈에 테스트 관련 의존성을 전파하지 않으며, core 모듈 내부에서만 사용된다.

2. 공유할 테스트 코드 설정 작성 (ex. Config 파일)

public abstract class <BaseAcceptanceTest {
    static MySQLContainer<?> mysqlContainer;
    
    @BeforeAll
    static void startContainer() {
        mysqlContainer = new MySQLContainer<>("mysql:8.0")
                .withDatabaseName("testdb")
                .withUsername("test")
                .withPassword("test")
                .withReuse(true);  // 컨테이너 재사용으로 속도 향상
        
        mysqlContainer.start();
    }
    
    @AfterAll
    static void stopContainer() {
        if (mysqlContainer != null) {
            mysqlContainer.stop();
        }
    }
    
    @DynamicPropertySource
    static void registerProperties(DynamicPropertyRegistry registry) {
        registry.add("spring.datasource.url", mysqlContainer::getJdbcUrl);
        registry.add("spring.datasource.username", mysqlContainer::getUsername);
        registry.add("spring.datasource.password", mysqlContainer::getPassword);
        registry.add("spring.datasource.driver-class-name", () -> "com.mysql.cj.jdbc.Driver");
    }
}

java-test-fixtures 플러그인 활성화 후 IntelliJ에서 New → Directory 선택 시 testFixtures 옵션이 나타난다. 반드시 src/testFixtures 폴더 하위에서 코드를 작성해야 하위 모듈에서 접근이 가능하다. 그 외 폴더에 있는 코드는 하위 모듈에서 참조할 수 없다.

3. 하위 모듈에서 테스트 옵션 사용

3-1. 의존성 추가

dependencies {
    implementation project(':core')
    testImplementation(testFixtures(project(':core')))
}

하위 모듈의 build.gradle에서 testImplementation 을 통해 core 모듈의 testFixtures 코드를 참조하여 사용할 수 있다. project 안에 받아올 모듈 이름을 적어주면 된다. 만약 모듈 이름이 core-web이라면 project(':core-web')처럼 작성하면 된다. 의존성을 추가하지 않으면 하위 모듈에서는 testFixtures 코드를 불러올 수 없다.

3-2. 코드에서 사용

class HealthControllerTest extends BaseAcceptanceTest {
    @Test
    void healthCheck() {
        // given & when
        ExtractableResponse<Response> response = RestAssured.given().log().all()
                .when()
                .get("/health/check")
                .then().log().all()
                .extract();

        // then
        assertThat(response.statusCode()).isEqualTo(HttpStatus.OK.value());
    }
}

의존성을 추가하고 나면 core 모듈에서 정의한 설정을 하위 모듈에서 사용할 수 있다. 여기에서는 위에서 추가한 BaseAcceptanceTest를 상속받았기 때문에 Testcontainers 설정이 자동으로 적용되어 MySQL 컨테이너가 실행된다.

마치며


TestFixtures를 사용하니 각 모듈에서 공통으로 사용하는 코드를 편리하게 관리할 수 있었다. 테스트 코드를 작성할 때 중복 코드가 발생하는 것을 보며 '이게 최선일까?'라는 생각을 계속 했는데 TestFixtures를 적용하니 코드가 확실히 정돈된 느낌을 받았다.

참고 자료

Testing in Java & JVM projects
Gradle TestFixtures 이용하여 테스트 코드 중복 줄이기
[Gradle] Multi Module에서 testFixtures를 이용하여 테스트 코드 중복 줄이기
테스트 의존성 관리로 높은 품질의 테스트 코드 유지하기

profile
왔다 정보리

0개의 댓글