Three actions to provide 'undercover' code coverage reporting

52 views
Skip to first unread message

Stuart Roebuck

unread,
Feb 18, 2010, 10:54:39 AM2/18/10
to simple-build-tool
I've just got three actions working that give code coverage reporting
using undercover (http://code.google.com/p/undercover/).

The actions rely on the undercover jar and it's two dependency jars
being in project/build/lib/. They are:
asm-all-3.2.jar
commons-lang-2.4.jar
undercover-0.8.2.jar

The actions are:
instrument - instrument the code
test-coverage - run the tests on instrumented code
test-coverage-report - produce the nice report

During the run it produces three additional directories in your
target:
classes-inst - the instrumented main classes
test-classes-inst - the instrumented test classes (not used at
present)
coverage - the coverage report(s)

Here's the code that was just added to the end of my Project
definition for my Scala project. I imagine that someone out there can
turn this into a neat plugin and stick it up on GitHub much quicker
than I can. Anyone who can is free to do so.

Code starts here:

// Create code coverage task `instrument` which instruments the
compiled classes for the `undercover`
// code coverage tool...

lazy val instrument = instrumentAction

def instrumentAction =
instrumentTask().dependsOn(compile,testCompile)
.describedAs("Instrument project classes ready for code
coverage testing.")

def instrumentTask(): Task = task {
log.info("Instrumenting main classes")
instrumentClasses(mainCompilePath, outputPath / "classes-inst")
log.info("Instrumenting test classes")
instrumentClasses(testCompilePath, outputPath / "test-classes-
inst")
None
}

// Create a code coverage test task `test-coverage` which runs the
tests over the instrumented
// classes...

lazy val testCoverage = testCoverageAction

def testCoverageAction = testCoverageTask() dependsOn (instrument)

def testCoverageTask(): Task = {
var instTestClasspath = testClasspath.
--- (outputPath / "classes").
--- (outputPath / "test-classes").
+++ (outputPath / "classes-inst" / "classes").
+++ (outputPath / "test-classes-inst" / "classes").
+++ (rootProject.info.projectPath ** "undercover*.jar")

val coverageDataPath = outputPath / "coverage" / "undercover.cd"
log.debug("Coverage data path: " + coverageDataPath.absolutePath)

val settings = new undercover.runtime.UndercoverSettings()
settings.setCoverageSaveOnExit(true)
settings.setCoverageFile(coverageDataPath.asFile)
val propertiesFile = (outputPath / "classes-inst" /
"undercover.properties").asFile
settings.save(propertiesFile)

testTask(testFrameworks, instTestClasspath,
testCompileConditional.analysis, testOptions)
}

lazy val testCoverageReport = testCoverageReportAction

def testCoverageReportAction = testCoverageReportTask()
dependsOn(testCoverage)

def testCoverageReportTask(): Task = task {
val sourceFinder = new undercover.report.SourceFinder()
val sourcePathFiles = (testSources +++ mainSources).getFiles
val sourcePathsJavaList =
java.util.Arrays.asList(sourcePathFiles.toArray: _*)
sourceFinder.setSourcePaths(sourcePathsJavaList)

val metaDataFile = (outputPath / "classes-inst" /
"undercover.md").asFile
val coverageDataFile = (outputPath / "coverage" /
"undercover.cd").asFile
val builder = new
undercover.report.ReportDataBuilder(metaDataFile, coverageDataFile)
builder.setProjectName(projectName.toString)
builder.setSourceFinder(sourceFinder)
val reportData = builder.build()
val outputEncoding = "UTF-8"

val formats = List("html")
formats.foreach { format =>
log.info("Generating " + format + " report")
format match {
case "html" => {
val report = new undercover.report.html.HtmlReport()
report.setReportData(reportData)
val outputDirectory = (outputPath / "coverage" /
"html").asFile
report.setOutputDirectory(outputDirectory)
report.setEncoding(outputEncoding)
report.generate()
}
case "coberturaxml" => {
val report = new
undercover.report.xml.CoberturaXmlReport(reportData)
val outputFile = (outputPath / "coverage" /
"cobertura.xml").asFile
report.writeTo(outputFile, outputEncoding)
}
case "emmaxml" => {
val report = new
undercover.report.xml.EmmaXmlReport(reportData)
val outputFile = (outputPath / "coverage" /
"emma.xml").asFile
report.writeTo(outputFile, outputEncoding)
}
case _ => log.warn("Unknown report format: " + format)
}
}

None
}

/**
* Use undercover to instrument the compiled main and test classes
and put them in instrumented
* classes directories within the target directory.
*/
private def instrumentClasses(inputPath: Path, outputPath: Path) {

val instr = new undercover.instrument.OfflineInstrument()
val paths = new java.util.ArrayList[java.io.File]()
paths.add(inputPath.asFile)
instr.setInstrumentPaths(paths)

instr.setOutputDirectory(outputPath.asFile)

val globFilter = new
undercover.instrument.filter.GlobFilter(Array[String](), Array[String]
())
instr.setFilter(globFilter)

val metaFile = (outputPath / "undercover.md").asFile
instr.setMetaDataFile(metaFile)

instr.fullcopy()
}

Doug Tangren

unread,
Feb 18, 2010, 11:21:55 AM2/18/10
to simple-b...@googlegroups.com
neat!
-Doug Tangren
http://lessis.me



--
You received this message because you are subscribed to the Google Groups "simple-build-tool" group.
To post to this group, send email to simple-b...@googlegroups.com.
To unsubscribe from this group, send email to simple-build-t...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/simple-build-tool?hl=en.


Reply all
Reply to author
Forward
0 new messages