From 0f6a936ffdd14f1ae8c9b5166384490f530b379e Mon Sep 17 00:00:00 2001 From: chanho0908 Date: Thu, 18 Dec 2025 15:59:21 +0900 Subject: [PATCH 1/5] =?UTF-8?q?=E2=9C=85=20=EC=BD=94=EB=A3=A8=ED=8B=B4=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=ED=99=98=EA=B2=BD=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=EB=B0=8F=20core:test=20=EB=AA=A8=EB=93=88=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - core:test 모듈 추가 (JUnit5 + Coroutines Test 지원) - FeatureConventionPlugin에 testImplementation 자동 의존성 추가 - DependencyHandlerScope에 testImplementation(Project) 확장 함수 추가 - ExampleTest.kt로 코루틴 테스트 예제 작성 🤖 Generated with [Firebender](https://firebender.com) Co-Authored-By: Firebender --- .../convention/FeatureConventionPlugin.kt | 2 ++ .../DependencyHandlerScopeExtension.kt | 4 +++ core/test/build.gradle.kts | 8 ++++++ .../com/twix/test/CoroutinesTestExtension.kt | 25 +++++++++++++++++ .../src/test/java/com/twix/login/.gitkeep | 0 .../test/java/com/twix/login/ExampleTest.kt | 28 +++++++++++++++++++ settings.gradle.kts | 1 + 7 files changed, 68 insertions(+) create mode 100644 core/test/build.gradle.kts create mode 100644 core/test/src/main/java/com/twix/test/CoroutinesTestExtension.kt delete mode 100644 feature/login/src/test/java/com/twix/login/.gitkeep create mode 100644 feature/login/src/test/java/com/twix/login/ExampleTest.kt diff --git a/build-logic/convention/src/main/kotlin/com/twix/convention/FeatureConventionPlugin.kt b/build-logic/convention/src/main/kotlin/com/twix/convention/FeatureConventionPlugin.kt index 4769500..9bdec8a 100644 --- a/build-logic/convention/src/main/kotlin/com/twix/convention/FeatureConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/com/twix/convention/FeatureConventionPlugin.kt @@ -2,6 +2,7 @@ package com.twix.convention import com.twix.convention.extension.applyPlugins import com.twix.convention.extension.implementation +import com.twix.convention.extension.testImplementation import org.gradle.kotlin.dsl.dependencies class FeatureConventionPlugin : BuildLogicConventionPlugin({ @@ -16,5 +17,6 @@ class FeatureConventionPlugin : BuildLogicConventionPlugin({ implementation(project(":core:navigation")) implementation(project(":core:ui")) implementation(project(":domain")) + testImplementation(project(":core:test")) } }) diff --git a/build-logic/convention/src/main/kotlin/com/twix/convention/extension/DependencyHandlerScopeExtension.kt b/build-logic/convention/src/main/kotlin/com/twix/convention/extension/DependencyHandlerScopeExtension.kt index fe7303f..bd2ad45 100644 --- a/build-logic/convention/src/main/kotlin/com/twix/convention/extension/DependencyHandlerScopeExtension.kt +++ b/build-logic/convention/src/main/kotlin/com/twix/convention/extension/DependencyHandlerScopeExtension.kt @@ -20,6 +20,10 @@ fun DependencyHandlerScope.androidTestImplementation(provider: Provider<*>) { "androidTestImplementation"(provider) } +fun DependencyHandlerScope.testImplementation(project: Project) { + "testImplementation"(project) +} + fun DependencyHandlerScope.testImplementation(provider: Provider<*>) { "testImplementation"(provider) } diff --git a/core/test/build.gradle.kts b/core/test/build.gradle.kts new file mode 100644 index 0000000..cd3cad4 --- /dev/null +++ b/core/test/build.gradle.kts @@ -0,0 +1,8 @@ +plugins { + alias(libs.plugins.twix.java.library) +} + +dependencies { + api(libs.kotlinx.coroutines.test) + api(libs.junit.jupiter) +} diff --git a/core/test/src/main/java/com/twix/test/CoroutinesTestExtension.kt b/core/test/src/main/java/com/twix/test/CoroutinesTestExtension.kt new file mode 100644 index 0000000..aa48cbd --- /dev/null +++ b/core/test/src/main/java/com/twix/test/CoroutinesTestExtension.kt @@ -0,0 +1,25 @@ +package com.twix.test + +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.TestDispatcher +import kotlinx.coroutines.test.UnconfinedTestDispatcher +import kotlinx.coroutines.test.resetMain +import kotlinx.coroutines.test.setMain +import org.junit.jupiter.api.extension.AfterEachCallback +import org.junit.jupiter.api.extension.BeforeEachCallback +import org.junit.jupiter.api.extension.ExtensionContext + +@ExperimentalCoroutinesApi +class CoroutinesTestExtension( + private val testDispatcher: TestDispatcher = UnconfinedTestDispatcher() +) : BeforeEachCallback, AfterEachCallback { + + override fun beforeEach(context: ExtensionContext?) { + Dispatchers.setMain(testDispatcher) + } + + override fun afterEach(context: ExtensionContext?) { + Dispatchers.resetMain() + } +} diff --git a/feature/login/src/test/java/com/twix/login/.gitkeep b/feature/login/src/test/java/com/twix/login/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/feature/login/src/test/java/com/twix/login/ExampleTest.kt b/feature/login/src/test/java/com/twix/login/ExampleTest.kt new file mode 100644 index 0000000..ad3f928 --- /dev/null +++ b/feature/login/src/test/java/com/twix/login/ExampleTest.kt @@ -0,0 +1,28 @@ +package com.twix.login + +import com.twix.test.CoroutinesTestExtension +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.runTest +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@OptIn(ExperimentalCoroutinesApi::class) +@ExtendWith(CoroutinesTestExtension::class) +class ExampleTest { + + @Test + fun `코루틴 테스트 예제`() = runTest { + // Given + val expected = "Hello, Coroutines!" + + // When + val actual = suspendFunction() + + // Then + assert(actual == expected) + } + + private suspend fun suspendFunction(): String { + return "Hello, Coroutines!" + } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index 9cc7038..9d19157 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -34,3 +34,4 @@ include(":core:ui") include(":core:navigation") include(":core:design-system") include(":core:network") +include(":core:test") From f51dc741fc5d6c09331cc53a890e7d88b586d770 Mon Sep 17 00:00:00 2001 From: chanho0908 Date: Thu, 18 Dec 2025 16:26:50 +0900 Subject: [PATCH 2/5] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Convention=20Plugin=20?= =?UTF-8?q?=EC=A4=91=EB=B3=B5=20=EC=A0=9C=EA=B1=B0=20=EB=B0=8F=20=EA=B5=AC?= =?UTF-8?q?=EC=A1=B0=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 개선 사항 ### 1. Compose 의존성 중복 제거 - AndroidComposeConventionPlugin에서 중복 의존성 선언 제거 - configureCompose() 함수에서 일괄 관리 ### 2. kotlinx-coroutines-core 중복 제거 - AndroidLibraryConventionPlugin에서 한 번만 선언 - DataConventionPlugin에서 중복 제거 (상위에서 상속) ### 3. 테스트 의존성 분리 - AndroidTestConventionPlugin 신규 추가 - 모든 모듈에 자동 추가되던 테스트 의존성을 선택적으로 적용 가능 - 테스트가 필요한 모듈에서만 명시적으로 적용 ### 4. AndroidLibraryConventionPlugin 최적화 - 불필요한 테스트 의존성 제거 - 기본 코루틴 의존성만 유지 ## 장점 - 빌드 시간 단축 (불필요한 의존성 감소) - 명확한 의존성 관리 - 유지보수성 향상 🤖 Generated with [Firebender](https://firebender.com) Co-Authored-By: Firebender --- build-logic/convention/build.gradle.kts | 4 ++++ .../twix/convention/AndroidComposeConventionPlugin.kt | 8 -------- .../twix/convention/AndroidLibraryConventionPlugin.kt | 3 +-- .../twix/convention/AndroidTestConventionPlugin.kt | 11 +++++++++++ .../com/twix/convention/DataConventionPlugin.kt | 7 ++----- gradle/libs.versions.toml | 1 + 6 files changed, 19 insertions(+), 15 deletions(-) create mode 100644 build-logic/convention/src/main/kotlin/com/twix/convention/AndroidTestConventionPlugin.kt diff --git a/build-logic/convention/build.gradle.kts b/build-logic/convention/build.gradle.kts index 289fe7d..96c9a25 100644 --- a/build-logic/convention/build.gradle.kts +++ b/build-logic/convention/build.gradle.kts @@ -35,6 +35,10 @@ gradlePlugin { id = "twix.android.compose" implementationClass = "com.twix.convention.AndroidComposeConventionPlugin" } + register("androidTest"){ + id = "twix.android.test" + implementationClass = "com.twix.convention.AndroidTestConventionPlugin" + } register("feature"){ id = "twix.feature" implementationClass = "com.twix.convention.FeatureConventionPlugin" diff --git a/build-logic/convention/src/main/kotlin/com/twix/convention/AndroidComposeConventionPlugin.kt b/build-logic/convention/src/main/kotlin/com/twix/convention/AndroidComposeConventionPlugin.kt index 337b91e..e556b0e 100644 --- a/build-logic/convention/src/main/kotlin/com/twix/convention/AndroidComposeConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/com/twix/convention/AndroidComposeConventionPlugin.kt @@ -3,7 +3,6 @@ package com.twix.convention import com.android.build.api.dsl.LibraryExtension import com.twix.convention.extension.* import org.gradle.kotlin.dsl.configure -import org.gradle.kotlin.dsl.dependencies class AndroidComposeConventionPlugin : BuildLogicConventionPlugin({ applyPlugins("org.jetbrains.kotlin.plugin.compose") @@ -11,11 +10,4 @@ class AndroidComposeConventionPlugin : BuildLogicConventionPlugin({ extensions.configure { configureCompose(this) } - - dependencies { - val bom = platform(libs.library("compose-bom")) - implementation(bom) - implementation(libs.bundle("compose")) - debugImplementation(libs.bundle("compose-debug")) - } }) diff --git a/build-logic/convention/src/main/kotlin/com/twix/convention/AndroidLibraryConventionPlugin.kt b/build-logic/convention/src/main/kotlin/com/twix/convention/AndroidLibraryConventionPlugin.kt index 6920738..8ca3f76 100644 --- a/build-logic/convention/src/main/kotlin/com/twix/convention/AndroidLibraryConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/com/twix/convention/AndroidLibraryConventionPlugin.kt @@ -18,8 +18,7 @@ class AndroidLibraryConventionPlugin : BuildLogicConventionPlugin({ } dependencies { + // 기본 코루틴 의존성 (Android 모듈 공통) implementation(libs.library("kotlinx-coroutines-core")) - testImplementation(libs.bundle("test-unit")) - androidTestImplementation(libs.library("androidx-test-ext-junit")) } }) diff --git a/build-logic/convention/src/main/kotlin/com/twix/convention/AndroidTestConventionPlugin.kt b/build-logic/convention/src/main/kotlin/com/twix/convention/AndroidTestConventionPlugin.kt new file mode 100644 index 0000000..39699e6 --- /dev/null +++ b/build-logic/convention/src/main/kotlin/com/twix/convention/AndroidTestConventionPlugin.kt @@ -0,0 +1,11 @@ +package com.twix.convention + +import com.twix.convention.extension.* +import org.gradle.kotlin.dsl.dependencies + +class AndroidTestConventionPlugin : BuildLogicConventionPlugin({ + dependencies { + testImplementation(libs.bundle("test-unit")) + androidTestImplementation(libs.library("androidx-test-ext-junit")) + } +}) diff --git a/build-logic/convention/src/main/kotlin/com/twix/convention/DataConventionPlugin.kt b/build-logic/convention/src/main/kotlin/com/twix/convention/DataConventionPlugin.kt index 014078d..58388a1 100644 --- a/build-logic/convention/src/main/kotlin/com/twix/convention/DataConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/com/twix/convention/DataConventionPlugin.kt @@ -1,7 +1,6 @@ package com.twix.convention import com.twix.convention.extension.* -import org.gradle.kotlin.dsl.dependencies class DataConventionPlugin : BuildLogicConventionPlugin({ applyPlugins( @@ -9,8 +8,6 @@ class DataConventionPlugin : BuildLogicConventionPlugin({ "org.jetbrains.kotlin.plugin.serialization", "twix.koin" ) - - dependencies { - implementation(libs.library("kotlinx-coroutines-core")) - } + + // kotlinx-coroutines-core는 twix.android.library에서 이미 추가됨 }) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7cc8770..0f86776 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -173,6 +173,7 @@ android-library = { id = "com.android.library", version.ref = "agp" } twix-android-application = { id = "twix.android.application", version = "unspecified" } twix-android-library = { id = "twix.android.library", version = "unspecified" } twix-android-compose = { id = "twix.android.compose", version = "unspecified" } +twix-android-test = { id = "twix.android.test", version = "unspecified" } twix-feature = { id = "twix.feature", version = "unspecified" } twix-koin = { id = "twix.koin", version = "unspecified" } twix-java-library = { id = "twix.java.library", version = "unspecified" } From fa35dac6c5891b33b1ca8d7cb92d75bd56b28aa7 Mon Sep 17 00:00:00 2001 From: chanho0908 Date: Thu, 18 Dec 2025 16:30:18 +0900 Subject: [PATCH 3/5] =?UTF-8?q?=F0=9F=90=9B=20FeatureConventionPlugin?= =?UTF-8?q?=EC=97=90=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=ED=94=8C=EB=9F=AC?= =?UTF-8?q?=EA=B7=B8=EC=9D=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - twix.android.test 플러그인 자동 적용 - Feature 모듈은 기본적으로 테스트를 포함하므로 자동 추가 - ExampleTest 실행 오류 수정 🤖 Generated with [Firebender](https://firebender.com) Co-Authored-By: Firebender --- .../main/kotlin/com/twix/convention/FeatureConventionPlugin.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/build-logic/convention/src/main/kotlin/com/twix/convention/FeatureConventionPlugin.kt b/build-logic/convention/src/main/kotlin/com/twix/convention/FeatureConventionPlugin.kt index 9bdec8a..1e335cc 100644 --- a/build-logic/convention/src/main/kotlin/com/twix/convention/FeatureConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/com/twix/convention/FeatureConventionPlugin.kt @@ -9,6 +9,7 @@ class FeatureConventionPlugin : BuildLogicConventionPlugin({ applyPlugins( "twix.android.library", "twix.android.compose", + "twix.android.test", "twix.koin", ) From 8a3d693e3ab891c552c0f32a82a63ba4d49d540e Mon Sep 17 00:00:00 2001 From: chanho0908 Date: Thu, 18 Dec 2025 16:30:18 +0900 Subject: [PATCH 4/5] =?UTF-8?q?=F0=9F=90=9B=20FeatureConventionPlugin?= =?UTF-8?q?=EC=97=90=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=ED=94=8C=EB=9F=AC?= =?UTF-8?q?=EA=B7=B8=EC=9D=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - twix.android.test 플러그인 자동 적용 - Feature 모듈은 기본적으로 테스트를 포함하므로 자동 추가 - ExampleTest 실행 오류 수정 --- .../AndroidLibraryConventionPlugin.kt | 1 - .../twix/convention/DataConventionPlugin.kt | 2 -- .../com/twix/test/CoroutinesTestExtension.kt | 6 ++-- .../test/java/com/twix/login/ExampleTest.kt | 28 +++++++++---------- 4 files changed, 16 insertions(+), 21 deletions(-) diff --git a/build-logic/convention/src/main/kotlin/com/twix/convention/AndroidLibraryConventionPlugin.kt b/build-logic/convention/src/main/kotlin/com/twix/convention/AndroidLibraryConventionPlugin.kt index 8ca3f76..24cfdf1 100644 --- a/build-logic/convention/src/main/kotlin/com/twix/convention/AndroidLibraryConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/com/twix/convention/AndroidLibraryConventionPlugin.kt @@ -18,7 +18,6 @@ class AndroidLibraryConventionPlugin : BuildLogicConventionPlugin({ } dependencies { - // 기본 코루틴 의존성 (Android 모듈 공통) implementation(libs.library("kotlinx-coroutines-core")) } }) diff --git a/build-logic/convention/src/main/kotlin/com/twix/convention/DataConventionPlugin.kt b/build-logic/convention/src/main/kotlin/com/twix/convention/DataConventionPlugin.kt index 58388a1..d0e0dfc 100644 --- a/build-logic/convention/src/main/kotlin/com/twix/convention/DataConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/com/twix/convention/DataConventionPlugin.kt @@ -8,6 +8,4 @@ class DataConventionPlugin : BuildLogicConventionPlugin({ "org.jetbrains.kotlin.plugin.serialization", "twix.koin" ) - - // kotlinx-coroutines-core는 twix.android.library에서 이미 추가됨 }) diff --git a/core/test/src/main/java/com/twix/test/CoroutinesTestExtension.kt b/core/test/src/main/java/com/twix/test/CoroutinesTestExtension.kt index aa48cbd..1a9b94c 100644 --- a/core/test/src/main/java/com/twix/test/CoroutinesTestExtension.kt +++ b/core/test/src/main/java/com/twix/test/CoroutinesTestExtension.kt @@ -12,9 +12,9 @@ import org.junit.jupiter.api.extension.ExtensionContext @ExperimentalCoroutinesApi class CoroutinesTestExtension( - private val testDispatcher: TestDispatcher = UnconfinedTestDispatcher() -) : BeforeEachCallback, AfterEachCallback { - + private val testDispatcher: TestDispatcher = UnconfinedTestDispatcher(), +) : BeforeEachCallback, + AfterEachCallback { override fun beforeEach(context: ExtensionContext?) { Dispatchers.setMain(testDispatcher) } diff --git a/feature/login/src/test/java/com/twix/login/ExampleTest.kt b/feature/login/src/test/java/com/twix/login/ExampleTest.kt index ad3f928..954bb51 100644 --- a/feature/login/src/test/java/com/twix/login/ExampleTest.kt +++ b/feature/login/src/test/java/com/twix/login/ExampleTest.kt @@ -9,20 +9,18 @@ import org.junit.jupiter.api.extension.ExtendWith @OptIn(ExperimentalCoroutinesApi::class) @ExtendWith(CoroutinesTestExtension::class) class ExampleTest { - @Test - fun `코루틴 테스트 예제`() = runTest { - // Given - val expected = "Hello, Coroutines!" - - // When - val actual = suspendFunction() - - // Then - assert(actual == expected) - } - - private suspend fun suspendFunction(): String { - return "Hello, Coroutines!" - } + fun `코루틴 테스트 예제`() = + runTest { + // Given + val expected = "Hello, Coroutines!" + + // When + val actual = suspendFunction() + + // Then + assert(actual == expected) + } + + private suspend fun suspendFunction(): String = "Hello, Coroutines!" } From 976b20bf1374f680a245f6a3dfa0fbccfbfd2c4d Mon Sep 17 00:00:00 2001 From: chanho0908 Date: Sat, 20 Dec 2025 18:41:42 +0900 Subject: [PATCH 5/5] =?UTF-8?q?=E2=9E=95=20FeatureConventionPlugin?= =?UTF-8?q?=EC=97=90=20AndroidTestConventionPlugin=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Firebender](https://firebender.com) Co-Authored-By: Firebender --- .../main/kotlin/com/twix/convention/FeatureConventionPlugin.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/build-logic/convention/src/main/kotlin/com/twix/convention/FeatureConventionPlugin.kt b/build-logic/convention/src/main/kotlin/com/twix/convention/FeatureConventionPlugin.kt index 1f56f4c..42f28a4 100644 --- a/build-logic/convention/src/main/kotlin/com/twix/convention/FeatureConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/com/twix/convention/FeatureConventionPlugin.kt @@ -8,6 +8,7 @@ class FeatureConventionPlugin : BuildLogicConventionPlugin({ apply() apply() apply() + apply() dependencies { implementation(project(":core:design-system"))