Comprehensive code coverage tool for Scala providing statement and branch coverage through compiler plugin instrumentation and report generation
—
The coverage data model provides the core data structures for representing coverage information including statements, classes, methods, packages, and files with comprehensive coverage metrics. This model forms the foundation for all coverage analysis and reporting functionality.
The main container for all coverage data and analysis.
case class Coverage() extends CoverageMetrics
with MethodBuilders
with ClassBuilders
with PackageBuilders
with FileBuilders {
def add(stmt: Statement): Unit
def addIgnoredStatement(stmt: Statement): Unit
def apply(ids: Iterable[(Int, String)]): Unit
def invoked(id: (Int, String)): Unit
// Aggregation methods
def avgClassesPerPackage: Double
def avgClassesPerPackageFormatted: String
def avgMethodsPerClass: Double
def avgMethodsPerClassFormatted: String
def loc: Int
def linesPerFile: Double
def linesPerFileFormatted: String
def risks(limit: Int): Seq[MeasuredClass]
}Key Methods:
add(stmt: Statement) - Add a statement to coverage trackingaddIgnoredStatement(stmt: Statement) - Add a statement that should be ignoredapply(ids: Iterable[(Int, String)]) - Apply measurement data to mark statements as invokedinvoked(id: (Int, String)) - Mark a specific statement as invokedrisks(limit: Int) - Get classes with lowest coverage (highest risk)Represents a single instrumented statement in the source code.
case class Statement(
location: Location,
id: Int,
start: Int,
end: Int,
line: Int,
desc: String,
symbolName: String,
treeName: String,
branch: Boolean,
count: Int = 0,
ignored: Boolean = false,
tests: mutable.Set[String] = mutable.Set[String]()
) {
def source: String
def invoked(test: String): Unit
def isInvoked: Boolean
}Parameters:
location - Source code location informationid - Unique identifier for the statementstart - Character offset start position in source fileend - Character offset end position in source fileline - Line number in source filedesc - Human-readable description of the statementsymbolName - Scala symbol name (e.g., "scala.Predef.println")treeName - Scala compiler tree type (e.g., "Apply", "Select")branch - Whether this statement represents a branch pointcount - Number of times statement was executedignored - Whether statement should be excluded from coveragetests - Set of test names that executed this statementContains source code location information for statements.
case class Location(
packageName: String,
className: String,
fullClassName: String,
classType: ClassType,
method: String,
sourcePath: String
)Parameters:
packageName - Package containing the statementclassName - Simple class namefullClassName - Fully qualified class nameclassType - Type of class (Class, Object, or Trait)method - Method containing the statementsourcePath - Absolute path to source fileRepresents coverage metrics for a single class.
case class MeasuredClass(
fullClassName: String,
statements: Iterable[Statement]
) extends CoverageMetrics with MethodBuilders {
def source: String
def loc: Int
def displayClassName: String
}Key Properties:
source - Path to source file containing the classloc - Lines of code (highest line number with a statement)displayClassName - Class name without package prefix for displayRepresents coverage metrics for a single method.
case class MeasuredMethod(
name: String,
statements: Iterable[Statement]
) extends CoverageMetricsParameters:
name - Method name with signature informationstatements - All statements contained in this methodRepresents coverage metrics for a package.
case class MeasuredPackage(
name: String,
statements: Iterable[Statement]
) extends CoverageMetrics with ClassCoverage with ClassBuilders with FileBuildersParameters:
name - Package name (fully qualified)statements - All statements in the packageRepresents coverage metrics for a source file.
case class MeasuredFile(
source: String,
statements: Iterable[Statement]
) extends CoverageMetrics with ClassCoverage with ClassBuilders {
def filename: String
def loc: Int
}Key Properties:
filename - Just the filename without pathloc - Lines of code (highest line number with a statement)All measured types implement the CoverageMetrics trait providing standard coverage calculations.
trait CoverageMetrics {
def statements: Iterable[Statement]
def ignoredStatements: Iterable[Statement]
// Statement metrics
def statementCount: Int
def ignoredStatementCount: Int
def invokedStatements: Iterable[Statement]
def invokedStatementCount: Int
def statementCoverage: Double
def statementCoveragePercent: Double
def statementCoverageFormatted: String
// Branch metrics
def branches: Iterable[Statement]
def branchCount: Int
def invokedBranches: Iterable[Statement]
def invokedBranchesCount: Int
def branchCoverage: Double
def branchCoveragePercent: Double
def branchCoverageFormatted: String
}Statement Metrics:
statementCount - Total statementsinvokedStatementCount - Statements that were executedstatementCoverage - Coverage as decimal (0.0 to 1.0)statementCoveragePercent - Coverage as percentage (0.0 to 100.0)statementCoverageFormatted - Formatted percentage string (e.g., "85.67")Branch Metrics:
branchCount - Total branch pointsinvokedBranchesCount - Branch points that were executedbranchCoverage - Branch coverage as decimal (0.0 to 1.0)branchCoveragePercent - Branch coverage as percentage (0.0 to 100.0)branchCoverageFormatted - Formatted branch coverage percentageEnumeration for different types of Scala classes.
sealed trait ClassType
object ClassType {
case object Object extends ClassType
case object Class extends ClassType
case object Trait extends ClassType
def fromString(str: String): ClassType
}Generates highlighted source code display with coverage information for HTML reports.
class CodeGrid(mFile: MeasuredFile, sourceEncoding: Option[String]) {
val highlighted: String
}
// Backward compatibility constructor
class CodeGrid(mFile: MeasuredFile)Key Properties:
highlighted: String - HTML string with source code and coverage highlightingRepresents the execution status of a statement for display purposes.
sealed trait StatementStatus
case object Invoked extends StatementStatus
case object NotInvoked extends StatementStatus
case object NoData extends StatementStatusUtility class for working with class references.
case class ClassRef(name: String) {
lazy val simpleName: String
lazy val getPackage: String
}
object ClassRef {
def fromFilepath(path: String): ClassRef
def apply(_package: String, className: String): ClassRef
}Provides method aggregation functionality.
trait MethodBuilders {
def statements: Iterable[Statement]
def methods: Seq[MeasuredMethod]
def methodCount: Int
}Provides package aggregation functionality.
trait PackageBuilders {
def statements: Iterable[Statement]
def packages: Seq[MeasuredPackage]
def packageCount: Int
}Provides class aggregation functionality.
trait ClassBuilders {
def statements: Iterable[Statement]
def classes: Iterable[MeasuredClass]
def classCount: Int
}Provides file aggregation functionality.
trait FileBuilders {
def statements: Iterable[Statement]
def files: Iterable[MeasuredFile]
def fileCount: Int
}import scoverage.domain._
// Create a new coverage container
val coverage = Coverage()
// Create a statement
val location = Location(
packageName = "com.example",
className = "MyClass",
fullClassName = "com.example.MyClass",
classType = ClassType.Class,
method = "myMethod",
sourcePath = "/path/to/MyClass.scala"
)
val statement = Statement(
location = location,
id = 1,
start = 100,
end = 120,
line = 10,
desc = "println(\"Hello\")",
symbolName = "scala.Predef.println",
treeName = "Apply",
branch = false
)
// Add statement to coverage
coverage.add(statement)// Measurement data represents which statements were executed
val measurements = Set(
(1, "com.example.MyTest"), // Statement 1 was hit by MyTest
(2, "com.example.MyTest"), // Statement 2 was hit by MyTest
(3, "") // Statement 3 was hit but test name unknown
)
// Apply measurements to coverage
coverage.apply(measurements)
// Check coverage metrics
println(s"Statement coverage: ${coverage.statementCoverageFormatted}%")
println(s"Branch coverage: ${coverage.branchCoverageFormatted}%")// Get classes with lowest coverage (highest risk)
val riskyClasses = coverage.risks(10)
riskyClasses.foreach { cls =>
println(s"${cls.fullClassName}: ${cls.statementCoverageFormatted}% coverage")
}
// Analyze by package
coverage.packages.foreach { pkg =>
println(s"Package ${pkg.name}: ${pkg.statementCoverageFormatted}% coverage")
// Analyze classes in package
pkg.classes.foreach { cls =>
println(s" Class ${cls.displayClassName}: ${cls.statementCoverageFormatted}%")
}
}// Analyze file-level coverage
coverage.files.foreach { file =>
println(s"File ${file.filename}: ${file.statementCoverageFormatted}% coverage, ${file.loc} LOC")
// Check methods in file
file.methods.foreach { method =>
println(s" Method ${method.name}: ${method.statementCoverageFormatted}% coverage")
}
}Data Integrity:
Common Issues:
Install with Tessl CLI
npx tessl i tessl/maven-org-scoverage--scalac-scoverage-plugin