티스토리 뷰
Springboot + Gradle 조합을 사용한다면 소규모 이상의 프로젝트에서 적용할 수 있는 꿀팁이 있다
프로젝트 루트 경로에 있는 .gradle 폴더 안에 gradle.yml을 이용해 캐싱, 병렬 실행, jvm memory 설정을 줄 수 있다
gradle.properties 도 가능하지만 가독성 & 중복 제거 측면에서 yml을 쓰는 것이 낫다
더 멋들어진 설정이 있나 찾아봤었는데 대충 요 정도만 쓰는 거 같다
.gradle/gradle.yml
org:
gradle:
daemon: true
caching: true
parallel: true
jvmargs: -Xmx2048m
configureondemand: true
gradle.yml을 작성했다면 터미널에서 아래 명령어들을 이용해 프로젝트 전체 테스트를 돌릴 수 있다
멀티 모듈 프로젝트를 진행하는 경우엔 테스트 시간 단축이 꽤나 많이 되므로 사용을 추천한다
./gradlew build --parallel 빌드 수행
./gradlew test --parallel 테스트만 수행
./gradlew -x test build --parallel 테스트 없이 빌드 수행
위에까지 진행했다면 아주 적은 노력으로 효율이 높아졌을 것이고 한 동안은 기능 개발에만 몰두할 수 있을 것이다
그러다 프로젝트가 충분히 커지고, 테스트 코드가 충분히 쌓일 때쯤 내가 만난 것과 비슷한 유형의 에러를 만날지도 모른다
프로젝트에 jacoco를 추가하면 아래와 같이 이쁜 test reports를 만들어준다, 전체 stack trace가 아닌 일부분을 올린다
아무리 돌려봐도 얘네 둘만 실패하니까 당연히 이 메서드 둘이 문제 있을 거라 생각했다
둘이 데이터가 꼬였나? 전체 조회는 2가 나와야 하는데 왜 3이 나올까? 전체 회원 조회는 1이 나와야 하는데 왜 2가 나올까?
삽질과 고뇌의 시간을 한참 보낸 후 문제 해결은 간단히 됐다
jacoco가 만들어주는 테스트 결과 reports에는 Standard output 이 있다
@SpringBootTest를 돌릴 시 컨테이너 생성부터의 모든 로그를 보여주는 녀석이고 테스트 코드 상에 써둔 로그 또한 찍힌다
문제가 된 테스트 코드는 Service 계층에서 List<DTO> 형태로 결과를 받아와 List.size()로 크기를 찾아 검증하는 로직인데
MemberResponse의 id 4, 5는 내가 의도해서 생성한 것이고 id 1번은 나도 초면이다
Service 담당 모듈에서의 테스트 구조이고 병렬 실행으로 인해 값이 공유돼버린 두 클래스다
service/member/MemberServiceTest
service/member/mapper/MemberResponseMapperTest
두 테스트 모두 @SpringBootTest를 이용해 테스트를 돌리던 중이었기 때문에 발생한 문제다
순차 실행으로 돌리면 테스트 클래스 / 메서드에 걸어주는 @Transactional로 인해 Rollback 되므로 걱정 없다
병렬 실행으로 돌리면 하나의 컨테이너에서 값이 공유될 수 있다는 것을 깊게 생각하지 못했다
MemberResponseMapperTest는 굳이 부트 테스트를 돌릴 필요가 없는 놈이라 애노테이션 빼고
그냥 평범한 테스트를 수행하게 만들었고 이후엔 값 공유 없이 잘 빌드되었다
병렬성의 무서움을 한방 맞아보며 느꼈다
특히 로컬에서 ./gradlew build --parallel로 돌릴 땐 테스트 순서가 오락가락할 때도 있어서 빌드되었다가
커밋 후에 CI를 위해 Github Actions에서 실행될 때 터지면 쫄깃해진다
무릇 github에 올라가는 commit 뒤에 빨간 마크는 개발자의 수치다
jacoco가 테스트 커버리지만 알려주는 놈인 줄 알았는데 요놈 덕에 병렬성 문제를 해결했다
고맙다 jacoco야 공부해서 더 굴려줄게!
'Spring > Spring Framework' 카테고리의 다른 글
[Spring] @Cacheable Cannot resolve bean 'cacheManager' (0) | 2021.12.17 |
---|---|
[Log4j2] CVE-2021-44228 대응 (0) | 2021.12.13 |
[Test] JPA DataIntegrityViolationException 발생 테스트 복구 (0) | 2021.11.19 |
[MapStruct] DTO 안의 DTO (0) | 2021.10.07 |
[Test] 깨지는 테스트 어떻게 복구할까? (3) | 2021.09.24 |