State of Kotlin Static Analysis

Less than a year ago I started using Kotlin to write micro-services. I was a Java developer, and mostly happy with that, but I took a liking to Kotlin immediately. In short order, I was writing cleaner, more robust code and seeing performance gains too!

The one area I wasn’t satisfied with in Kotlin was static code analysis. With Java grinding your code against static analysis tools was easy, and informative, it helped improve my code, and was vital for bringing junior folks, or outsiders, into a code base’s style and quality expectations.

Less Than A Year Ago

  • Jacoco: Crashed often on Kotlin, didn’t offer many insights, and didn’t understand Kotlin’s code generation leading to frustration code coverage numbers.
  • Ktlint and Detekt: Were young and it showed. They were hard to configure, really hard to employ as build gates, and rudimentary.
  • SonarQube, Codecov.io, Etc: With Jacoco feeding them, and broken, you can guess how well they worked…
  • IntelliJ’s Builtin Analysis: Meh. Worked but also kind of rudimentary.

Now, All That’s Changed

  • Jacoco: Now is reliable, more informative and fully understands Kotlin’s code generation.
  • Ktlint and Detekt: Have matured, have reliable plugins, are very informative, and can easily act as build gates.
  • SonarQube, Codecov.io, Etc: Well, ok, so SonarQube is still difficult, but Codecov.io rocks!
  • IntelliJ’s Builtin Analysis: Gotten better. I still, except for active hints, mostly prefer the others.

What You Need

  • Gradle: Get a new one, 5.5+, everything is easier with the newer builds.
  • Jacoco: Use the stock gradle plugin, and set the tool version to 0.8.3+.
  • Ktlint: Use the org.jlleitschuh.gradle.ktlint plugin, version 8.2.0+.
  • Detekt: Use the io.gitlab.arturbosch.detekt plugin, version 1.0.0-RC16+.
  • Editor Config: Take a look at this project for configuration convergence between IntelliJ and Ktlint.

What You’ll Get

You’ll get static analysis that offers real insights, idiomatic guidelines, accurate test coverage, one click auto-correction, and can be used to gate your build. I’ve even been able to cat herd Scala bigots with these tools.

Example

You can take a look at my ksvg project on github, it uses all these and appears on Codecov.io with 99% coverage.

Gradle, JUnit5, Jacoco Working

The way information is dispersed on the Internet is pretty cool sometimes.  I’ve visited this same topic a couple times and never managed to get JUnit5 and Jacoco working with Gradle.  Fresh searches never turned up a working solution.  The other day, looking at my blog stats I saw an intriguing referrer to one of my past posts. The reference was from a blog written in Japanese. Google translate yielded an awkward version that seemed to offer a solution.  Since the Gradle code needed no translation I tried out some of the changes shown and – viola!

So, Here’s the Working Solution

The goal was to employ JUnit5, generate Jacoco reports, and feed those into Codecov.com. Here’s the snippet of working solution.

buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'org.junit.platform:junit-platform-gradle-plugin:1.1.0-RC1'
}
}
apply plugin: "jacoco"
apply plugin: 'org.junit.platform.gradle.plugin'
repositories {
jcenter()
}
dependencies {
compile 'org.junit.jupiter:junit-jupiter-api:5.1.0-RC1'
testRuntime 'org.junit.jupiter:junit-jupiter-engine:5.1.0-RC1'
}
junitPlatform.enableStandardTestTask true
jacoco {
toolVersion = '0.7.9'
applyTo junitPlatformTest
}
jacocoTestReport {
reports {
xml.enabled = true
html.enabled = true
}
}
view raw build.gradle hosted with ❤ by GitHub

I believe the secret sauce I missed was in lines 23 and 27.  To see the project that I tested this with, the repo is here.