[#31] feat: BuildService 이용한 gradle lifecycle 테스트

- test finished 경우에 result logging 출력을 위한 gradle lifecycle 테스트 진행중
- 전반적인 리팩토링
This commit is contained in:
Hanbin Lee
2023-01-24 02:23:05 +09:00
parent 15744f1a9a
commit f4951990cd
6 changed files with 115 additions and 41 deletions

1
.gitignore vendored
View File

@@ -24,6 +24,7 @@ bin/
out/
!**/src/main/**/out/
!**/src/test/**/out/
lib/
### NetBeans ###
/nbproject/private/

View File

@@ -2,6 +2,8 @@ import org.gradle.api.tasks.testing.logging.TestExceptionFormat
import org.gradle.api.tasks.testing.logging.TestLogEvent
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.springframework.boot.gradle.tasks.bundling.BootJar
import plugin.BuildLifecyclePlugin
import plugin.TestSummary
plugins {
id(Plugins.Spring.boot).version(Version.Spring.boot)
@@ -34,7 +36,10 @@ subprojects {
plugin(Plugins.Kotlin.kotlinJpa)
}
java.sourceCompatibility = JavaVersion.VERSION_17
java.apply {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
dependencies {
// Spring Boot Project
@@ -81,7 +86,6 @@ subprojects {
events = setOf(
TestLogEvent.FAILED,
TestLogEvent.SKIPPED,
TestLogEvent.STANDARD_OUT,
TestLogEvent.STANDARD_ERROR
)
@@ -98,53 +102,56 @@ subprojects {
override fun afterSuite(desc: TestDescriptor, result: TestResult) {
if (desc.parent != null) return
val summary = TestOutcome().apply {
add("${project.name}:${name} Test result: ${result.resultType}")
add("Test summary: ${result.testCount} tests, ${result.successfulTestCount} succeeded, ${result.failedTestCount} failed, ${result.skippedTestCount} skipped")
add("report file: ${reports.html.entryPoint}")
}
val summary = TestSummary(
projectName = project.name,
taskName = name,
result = result
)
if (result.resultType == TestResult.ResultType.SUCCESS) {
testResults.add(0, summary)
} else {
testResults.add(summary)
}
// if (result.resultType == TestResult.ResultType.SUCCESS) {
// testResults.add(0, summary)
// } else {
// testResults.add(summary)
// }
}
override fun beforeTest(testDescriptor: TestDescriptor?) {}
override fun afterTest(testDescriptor: TestDescriptor?, result: TestResult?) {}
})
}
// for logging when build finished
apply<BuildLifecyclePlugin>()
}
gradle.buildFinished {
if (testResults.isNotEmpty()) {
printResults(testResults)
}
}
//gradle.buildFinished {
// if (testResults.isNotEmpty()) {
// printResults(testResults)
// }
//}
fun printResults(allResults:List<TestOutcome>) {
val maxLength = allResults.maxOfOrNull { it.maxWidth() } ?: 0
//fun printResults(allResults:List<TestOutcome>) {
// val maxLength = allResults.maxOfOrNull { it.maxWidth() } ?: 0
//
// println("┌${"─".repeat(maxLength)}┐")
//
// println(allResults.joinToString("├${"─".repeat(maxLength)}┤\n") { testOutcome ->
// testOutcome.lines.joinToString("│\n│", "│", "│") {
// it + " ".repeat(maxLength - it.length)
// }
// })
//
// println("└${"─".repeat(maxLength)}┘")
//}
//
//val testResults by extra(mutableListOf<TestOutcome>()) // Container for tests summaries
println("┌${"─".repeat(maxLength)}┐")
println(allResults.joinToString("├${"─".repeat(maxLength)}┤\n") { testOutcome ->
testOutcome.lines.joinToString("│\n│", "│", "│") {
it + " ".repeat(maxLength - it.length)
}
})
println("└${"─".repeat(maxLength)}┘")
}
val testResults by extra(mutableListOf<TestOutcome>()) // Container for tests summaries
data class TestOutcome(val lines: MutableList<String> = mutableListOf()) {
fun add(line: String) {
lines.add(line)
}
fun maxWidth(): Int {
return lines.maxBy { it.length }?.length ?: 0
}
}
//data class TestOutcome(val lines: MutableList<String> = mutableListOf()) {
// fun add(line: String) {
// lines.add(line)
// }
//
// fun maxWidth(): Int {
// return lines.maxByOrNull { it.length }?.length ?: 0
// }
//}

View File

@@ -0,0 +1,19 @@
package plugin
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.internal.build.event.BuildEventListenerRegistryInternal
import org.gradle.invocation.DefaultGradle
class BuildLifecyclePlugin : Plugin<Project> {
override fun apply(project: Project) {
val gradle = project.gradle
val services = (gradle as DefaultGradle).services
val registry = services[BuildEventListenerRegistryInternal::class.java]
val operationService = gradle.sharedServices.registerIfAbsent("operationService", BuildOperationService::class.java) {}
registry.subscribe(operationService)
}
}

View File

@@ -0,0 +1,22 @@
package plugin
import org.gradle.api.services.BuildService
import org.gradle.api.services.BuildServiceParameters
import org.gradle.tooling.events.FinishEvent
import org.gradle.tooling.events.OperationCompletionListener
import org.gradle.tooling.events.task.TaskFinishEvent
abstract class BuildOperationService : BuildService<BuildServiceParameters.None>, OperationCompletionListener {
private val targetProjects = listOf("dongne-account-api", "dongne-service-api")
private val targetTask = "test"
override fun onFinish(event: FinishEvent?) {
if (event == null || event !is TaskFinishEvent) {
return
}
if (event.descriptor.taskPath in targetProjects.map { ":$it:$targetTask" }) {
println("####### onFinish 222 ${event}")
}
}
}

View File

@@ -0,0 +1,25 @@
package plugin
import org.gradle.api.tasks.testing.TestResult
data class TestSummary(
val projectName: String? = null,
val taskName: String? = null,
val result: TestResult,
val lines: MutableList<String> = mutableListOf()
) {
fun add(line: String) {
lines.add(line)
}
fun maxWidth(): Int {
return lines.maxByOrNull { it.length }?.length ?: 0
}
fun toLogList(): List<String> {
return listOf(
"${projectName}:${taskName} Test result: ${result.resultType}",
"Test summary: ${result.testCount} tests, ${result.successfulTestCount} succeeded, ${result.failedTestCount} failed, ${result.skippedTestCount} skipped"
)
}
}