Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Integrating scala code coverage tool jacoco into a play 2.2.x project

My goal is to integrate jacoco into my play 2.2.0 project. Different guides on the web I tried to follow mostly added to confusion not to closing in on the goal.

Adding to confusion

  • Most guides assume the existance of an build.sbt
    • which as it seems as been superseded by an build.scala with a different
  • There is a jacoco4sbt and a regular jacoco
    • which one is most appropiate for use with scala play framework 2

Current state

in plugins.sbt added

addSbtPlugin("de.johoop" % "jacoco4sbt" % "2.1.2")

in build.scala added

import de.johoop.jacoco4sbt.JacocoPlugin._
lazy val jacoco_settings = Defaults.defaultSettings ++ Seq(jacoco.settings: _*)

With these changes i don't get an "jacoco" task in sbt nor in the play console.

What are the appropriate steps to get this working?

Update As requested the content of the build.scala

import com.typesafe.sbt.SbtNativePackager._
import com.typesafe.sbt.SbtScalariform._
import play.Project._
import sbt.Keys._
import sbt._
import sbtbuildinfo.Plugin._
import de.johoop.jacoco4sbt.JacocoPlugin._

object BuildSettings {
  val buildOrganization = "XXXXX"
  val buildVersion      = "0.1"
  val buildScalaVersion = "2.10.2"
  val envConfig = "-Dsbt.log.format=false -Dconfig.file=" + Option(System.getProperty("env.config")).getOrElse("local.application")
  scalacOptions ++= Seq("-encoding", "UTF-8", "-deprecation", "-unchecked", "-feature")
  javaOptions += envConfig

  val buildSettings = Defaults.defaultSettings ++ Seq (
    organization := buildOrganization,
    version      := buildVersion,
    scalaVersion := buildScalaVersion
  )
}

object Resolvers {
  val remoteRepoUrl =  "XXXXXXXXXXXX" at "http://nexus.cXXXXX/content/repositories/snapshots/"
  val publishRepoUrl = "XXXXXXXXXXXX" at "http://nexus.ciXXXXXXXXXXXXXXXX/content/repositories/snapshots/"
}

object Dependencies {
  val ods =  "XXXXXXXXX" % "XXXXXX-ws" % "2.2.1-SNAPSHOT"
  val scalatest = "org.scalatest" %% "scalatest" % "2.0.M8" % "test"
  val mockito = "org.mockito" % "mockito-all" % "1.9.5" % "test"
}

object ApplicationBuild extends Build {

  import BuildSettings._
  import Dependencies._
  import Resolvers._

  // Sub-project specific dependencies
  val commonDeps = Seq(
    ods,
    scalatest,
    mockito
  )
  //val bN = settingKey[Int]("current build Number")
  val gitHeadCommitSha = settingKey[String]("current git commit SHA")
  val release = settingKey[Boolean]("Release")

  lazy val jacoco_settings = Defaults.defaultSettings ++ Seq(jacoco.settings: _*)

  lazy val nemo = play.Project(
    "nemo",
    path = file("."),
    settings = Defaults.defaultSettings ++ buildSettings ++
      Seq(libraryDependencies ++= commonDeps) ++
      Seq(scalariformSettings: _*) ++
      Seq(playScalaSettings: _*) ++
      buildInfoSettings ++
      jacoco_settings ++
      Seq(
        sourceGenerators in Compile <+= buildInfo,
        buildInfoKeys ++= Seq[BuildInfoKey](
          resolvers,
          libraryDependencies in Test,
          buildInfoBuildNumber,
          BuildInfoKey.map(name) { case (k, v) => "project" + k.capitalize -> v.capitalize },
          "envConfig" -> envConfig, // computed at project load time
          BuildInfoKey.action("buildTime") {
            System.currentTimeMillis
          } // re-computed each time at compile
        ),
        buildInfoPackage := "com.springer.nemo"
      ) ++
      Seq(resolvers += remoteRepoUrl) ++
      Seq(mappings in Universal ++= Seq(
        file("ops/rpm/start-server.sh") -> "start-server.sh",
        file("ops/rpm/stop-server.sh") -> "stop-server.sh"
      ))
  ).settings(version <<=  version in ThisBuild)

  lazy val nemoPackaging = Project(
    "nemoPackaging",
    file("nemoPackaging"),
    settings = Defaults.defaultSettings ++Seq(Packaging.settings:_*)
  )



  def publishSettings =
    Seq(
      publishTo := Option(publishRepoUrl),
      credentials += Credentials(
        "Repo", "http://mycompany.com/repo", "admin", "admin123"))

}

Note: jacoco is running with this but does not pick up our tests. Output:

jacoco:cover
[info] Compiling 1 Scala source to /home/schl14/work/nemo/target/scala-2.10/classes...
[info] ScalaTest
[info] Run completed in 13 milliseconds.
[info] Total number of tests run: 0
[info] Suites: completed 0, aborted 0
[info] Tests: succeeded 0, failed 0, canceled 0, ignored 0, pending 0
[info] All tests passed.
[info] Passed: Total 0, Failed 0, Errors 0, Passed 0
[info] No tests to run for nemo/jacoco:test
like image 588
Th 00 mÄ s Avatar asked Feb 15 '23 18:02

Th 00 mÄ s


2 Answers

I solved it by doing this.

Add the following to plugins.sbt

addSbtPlugin("de.johoop" % "jacoco4sbt" % "2.1.2")

In build.scala i added a new import

import de.johoop.jacoco4sbt.JacocoPlugin._

and added jacoco to the config section like this

lazy val xyz = play.Project(
    "xyz",
    path = file("."),
    settings = Defaults.defaultSettings
      jacoco.settings ++ //this is the important part. 
  ).settings(parallelExecution in jacoco.Config := false) //not mandatory but needed in `most cases as most test can not be run in parallel`

After these steps jacoco:cover was available in the sbt and play console and also discovers our tests.

like image 152
Th 00 mÄ s Avatar answered Feb 17 '23 08:02

Th 00 mÄ s


A better option for Scala code coverage is Scoverage which gives statement line coverage. https://github.com/scoverage/scalac-scoverage-plugin

Add to project/plugins.sbt:

addSbtPlugin("com.sksamuel.scoverage" % "sbt-scoverage" % "1.0.1")

Then run SBT with

sbt clean coverage test
like image 32
sksamuel Avatar answered Feb 17 '23 08:02

sksamuel