とうとうサーバーサイドKotlinに片足を踏み入れようとしています。アプリ本体だけでなく、ビルドスクリプト(build.gradle.kts
)もKotlinで書くと型があっていいのだとか。
でも、今まで動いていたあれやこれやが使えなくなって、正直二度手間感があります。というわけで、これのKotlin版。
動作確認バージョン
- Kotlin 1.6.21
- OpenJDK 17.0.5
- Gradle 7.5.1
- JaCoCo 0.8.8
ビルドファイル
こんな感じか。GroovyもKotlinもビルドスクリプトは雰囲気で書いているので自信なし。
import org.w3c.dom.Element
import javax.xml.parsers.DocumentBuilderFactory
plugins {
jacoco
}
tasks.test {
useJUnitPlatform()
finalizedBy(tasks.jacocoTestReport)
}
tasks.jacocoTestReport {
dependsOn(tasks.test)
reports {
xml.required.set(true)
html.required.set(true)
}
doLast {
val report = file("${jacoco.reportsDirectory.get()}/test/jacocoTestReport.xml")
printCoverage(report)
}
}
fun printCoverage(xml: File) {
if (!xml.exists()) return
val factory = DocumentBuilderFactory.newInstance()
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false)
val document = factory.newDocumentBuilder().parse(xml)
val metrics = LinkedHashMap<String, Double>()
val nodes = document.documentElement.childNodes
for (i in 0 until nodes.length) {
val node = nodes.item(i)
if (node is Element && node.nodeName == "counter") {
val type = node.getAttribute("type")
val covered = node.getAttribute("covered").toDouble()
val missed = node.getAttribute("missed").toDouble()
metrics[type] = (covered / (covered + missed)) * 100
}
}
logger.quiet("----- Code Coverage ----------")
metrics.forEach { (key, value) -> logger.quiet(" - %-11s: %6.2f%%".format(key, value)) }
logger.quiet("------------------------------")
}
出力イメージ
テスト実行するとカバレッジがコンソールに出力されます。
$ ./gradlew test
...
> Task :jacocoTestReport
----- Code Coverage ----------
- INSTRUCTION: 15.00%
- LINE : 28.00%
- COMPLEXITY : 25.00%
- METHOD : 25.00%
- CLASS : 60.00%
------------------------------
まとめ
GitLab CI などで必要になる、JaCoCoのカバレッジをコンソールに出力する方法のKotlin版を紹介しました。JaCoCo 本体で対応してくれてもよさそうなものですが、作者にその気はないので望みなしです。
他にも↑のPRにawkで抽出する方法なども紹介されているので、よかったら参考にどうぞ。