2017-08-03 157 views
0

我有一个SBT(Play Framework)多项目应用程序设置,如下所示。所有的子模块都在modules之下,但所有覆盖所有子模块的测试用例都在“root”项目中。SBT + JaCoCo未涵盖来自不同项目的所有“jacoco.includes”类

|-application 
    |-src 
    |-conf 
    |-modules 
    | |-proj1 
    | | |-src 
    | | |-conf 
    | | |-target 
    | |-proj2 
    | | |-src 
    | | |-conf 
    | | |-target 
    | |-proj3 
    | | |-src 
    | | |-conf 
    | | |-target 
    | |-proj4 
    |  |-src 
    |  |-conf 
    |  |-target 
    |-test 
    | |-src //I have test cases of all other projs here 
    |-build.sbt 
    |-plugins.sbt 

我的build.sbt看起来像这样。

name := """my-proj""" 

lazy val IntegrationTest = config("it") extend(Test) 

lazy val commonSettings = jacoco.settings ++ itJacoco.settings ++ Seq(
    organization := "me.abc", 
    version := "0.1.0", 
    scalaVersion := "2.11.7", 
    crossPaths := false, 
    routesGenerator := InjectedRoutesGenerator 
) 
lazy val appDependencies = Seq(
    cache, 
    "org.mockito" % "mockito-all" % "1.10.19" 
) 

lazy val scalacheck = "org.scalacheck" %% "scalacheck" % "1.13.4" 

lazy val aaRoot = (project in file(".")).configs(IntegrationTest).settings(commonSettings: _*).settings(
    libraryDependencies ++= appDependencies, 
    libraryDependencies += scalacheck % Test, 
    parallelExecution in Test := false, 
    javaOptions in Test += "-Dconfig.file=conf/" + Option(System.getProperty("test.config")).getOrElse("application") + ".conf", 
    parallelExecution in jacoco.Config := false, 
    jacoco.includes in jacoco.Config := Seq("./modules/*/target/classes/com/me/**/*"), 
    parallelExecution in itJacoco.Config := false, 
    itJacoco.includes in itJacoco.Config := Seq("./modules/*/target/classes/com/me/**/*"), 
    Keys.fork in itJacoco.Config := true, 
    Keys.fork in jacoco.Config := true 
).enablePlugins(PlayJava).disablePlugins(plugins.JUnitXmlReportPlugin).dependsOn(
    proj1 % "compile->compile", 
    proj2 % "compile->compile", 
    proj3 % "compile->compile", 
    proj4 % "compile->compile", 
).aggregate(
    proj1, 
    proj2, 
    proj3, 
    proj4 
) 

lazy val proj1 = (project in file("modules/proj1")).configs(IntegrationTest).settings(commonSettings: _*).settings(
    libraryDependencies ++= appDependencies 
).enablePlugins(PlayJava) 


fork in run := false 

PlayKeys.externalizeResources := false 

正如你所看到的,在aaRoot,我试图从jacoco.includes其他模块的目标文件夹中的类文件(我曾尝试其他几种方法,但是毫无效果)。所有的测试案例运行良好,但jacoco不能覆盖任何东西。

[info] ------- Jacoco Coverage Report -------- 
[info] 
[info] Lines: 0% (>= required 0.0%) covered, 0 of 0 missed, OK 
[info] Instructions: 0% (>= required 0.0%) covered, 0 of 0 missed, OK 
[info] Branches: 0% (>= required 0.0%) covered, 0 of 0 missed, OK 
[info] Methods: 0% (>= required 0.0%) covered, 0 of 0 missed, OK 
[info] Complexity: 0% (>= required 0.0%) covered, 0 of 0 missed, OK 
[info] Class: 0% (>= required 0.0%) covered, 0 of 0 missed, OK 
[info] Check /Users/RP/application/target/jacoco for detail report 

很明显,jacoco.includes不看我请求看的任何类。

我已经尝试了很多方法,并尝试使用it-jacoco:cover以及但没有任何工作。任何提示或帮助将appriciated。

回答

0

这是一个棘手的问题。我解决了我的问题,并使jacocosbt与我的项目设置一起工作,我认为我的项目设置不算太糟糕,也很正常。

我所拥有的是,根项目下的几个子项目和所有与子项目相关的测试用例都在根/测试中,以便我可以测试跨模块功能测试。

解决方案 阅读和理解jacocosbt插件的源代码后,我意识到,这取决于两个主要的事情。一种是classesToCover,另一种是“仪器类别”。

对于“仪器类”它取决于products in Compile这是当前项目中的“目标/类”文件夹。在我的情况下,“root/target/classes”没有任何内容,装备。我所有的课程都在“根/模块/模块1 /目标/类”等。

我只需要重写此行为。第一个很容易,第二个是解决方法。

在我build.sbt,我要补充以下修改

//Gets all the target/classes directories from sub projects 
lazy val myProducts = Def.task { 
    streams.value.log.info("Constructing the products!!!") 
    val finder: PathFinder = ((baseDirectory.value/"modules") ** "target" * "classes") filter {_.getAbsolutePath.indexOf("/project/") == -1} 
    finder.get 
} 

//Gets the classesToCover from all the sub projects 
lazy val myClassesToCover = Def.task { 
    val targetFolders: Seq[java.io.File] = myProducts.value 
    val inclFilters = Seq("*") map GlobFilter.apply 
    val exclFilters = Seq("Routes*","*Routes*","*Reverse*","*anonfun*", "*routes*") map GlobFilter.apply 

    targetFolders flatMap (classes => { 
    PathFinder(classes) ** new FileFilter { 
     def accept(f: File) = IO.relativize(classes, f) match { 
     case Some(file) if !f.isDirectory && file.endsWith(".class") => 
      val name = sbt.inc.Locate.toClassName(file) 
      inclFilters.exists(_ accept name) && !exclFilters.exists(_ accept name) 
     case _ => false 
    } 
    } get 
    }) 
} 

//Add them as settings for my root project 

lazy val root = (project in file(".")).settings(commonSettings: _*).settings(
    jacoco.settings, 
    parallelExecution in jacoco.Config := false, 
    Keys.fork in jacoco.Config := true, 
    jacoco.classesToCover in jacoco.Config ++= myClassesToCover.value, 
    products in Compile ++= myProducts.value 
).enablePlugins(PlayJava).disablePlugins(plugins.JUnitXmlReportPlugin).dependsOn(
    module1 % "test->test;compile->compile", 
    module2 % "test->test;compile->compile" 
).aggregate(
    module1, 
    module2 
) 

由于SBT compile任务依赖于products目标,我们应始终运行编译第一像>sbt compile jacoco:cover

我测试过这个只有jacocosbt插件版本2.1.6

相关问题