@@ -2,14 +2,15 @@ plugins {
22 id ' java'
33 id ' org.springframework.boot' version ' 3.5.4'
44 id ' io.spring.dependency-management' version ' 1.1.7'
5+ id ' jacoco'
56}
67
78group = ' com.example'
89version = ' 0.0.1-SNAPSHOT'
910
1011java {
1112 toolchain {
12- languageVersion = JavaLanguageVersion . of(17 )
13+ languageVersion = JavaLanguageVersion . of(21 )
1314 }
1415}
1516
2425dependencyManagement {
2526 imports {
2627 mavenBom " org.springframework.cloud:spring-cloud-dependencies:${ springCloudVersion} "
28+ mavenBom " org.testcontainers:testcontainers-bom:1.20.2"
2729 }
2830}
2931
@@ -38,6 +40,7 @@ dependencies {
3840 compileOnly ' org.projectlombok:lombok'
3941 developmentOnly ' org.springframework.boot:spring-boot-devtools'
4042 runtimeOnly ' com.mysql:mysql-connector-j'
43+ runtimeOnly ' com.h2database:h2'
4144 annotationProcessor ' org.projectlombok:lombok'
4245 testImplementation ' org.springframework.boot:spring-boot-starter-test'
4346 testImplementation ' org.springframework.security:spring-security-test'
@@ -65,8 +68,90 @@ dependencies {
6568 implementation ' software.amazon.awssdk:s3:2.32.11'
6669 // Redis
6770 implementation ' org.springframework.boot:spring-boot-starter-data-redis'
71+ testImplementation ' org.testcontainers:junit-jupiter'
72+ testImplementation ' org.testcontainers:testcontainers'
73+ // jpa 쿼리 확인
74+ implementation ' com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.9.0'
6875}
6976
7077tasks. named(' test' ) {
7178 useJUnitPlatform()
79+ finalizedBy jacocoTestReport
80+
81+ // notification 관련 테스트 임시 제외
82+ exclude ' **/AppNotificationControllerTest.class'
83+ exclude ' **/FcmServiceTest.class'
84+ exclude ' **/SseEmittersServiceTest.class'
85+ exclude ' **/AppNotificationTypeRepositoryTest.class'
86+ exclude ' **/search/**'
87+ exclude ' **/club/repository/**'
88+ }
89+
90+ jacoco {
91+ toolVersion = " 0.8.13"
92+ }
93+
94+ jacocoTestReport {
95+ dependsOn test
96+ reports {
97+ html. required = true
98+ xml. required = true
99+ csv. required = false
100+ html. outputLocation = layout. buildDirectory. dir(' jacocoHtml' )
101+ xml. outputLocation = layout. buildDirectory. file(' jacoco/jacoco.xml' )
102+ }
103+
104+ // 제외할 패키지/클래스 설정
105+ afterEvaluate {
106+ classDirectories. setFrom(files(classDirectories. files. collect {
107+ fileTree(dir : it, exclude : [
108+ // 설정 클래스들
109+ ' **/config/**' ,
110+ ' **/configuration/**' ,
111+
112+ // DTO/Entity/Enum 클래스들 (비즈니스 로직 없음)
113+ ' **/dto/**' ,
114+ ' **/entity/**' ,
115+ ' **/domain/**/entity/**' ,
116+
117+ // Application 시작 클래스
118+ ' **/*Application*' ,
119+
120+ // Exception 클래스들
121+ ' **/exception/**' ,
122+ ' **/global/exception/**' ,
123+
124+ // 기타 유틸리티
125+ ' **/util/**' ,
126+ ' **/common/**' ,
127+
128+ ' **/search/**' ,
129+ ' **/club/repository/**'
130+ ])
131+ }))
132+ }
133+ }
134+
135+ // 테스트 커버리지 최소 기준 설정
136+ jacocoTestCoverageVerification {
137+ dependsOn jacocoTestReport
138+ violationRules {
139+ rule {
140+ limit {
141+ minimum = 0.80 // 80% 커버리지 요구
142+ }
143+ }
144+
145+ rule {
146+ enabled = true
147+ element = ' CLASS'
148+ includes = [' com.example.onlyone.domain.*.service.*' ]
149+
150+ limit {
151+ counter = ' LINE'
152+ value = ' COVEREDRATIO'
153+ minimum = 0.75 // Service 클래스는 75% 이상
154+ }
155+ }
156+ }
72157}
0 commit comments