CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-scoverage--scalac-scoverage-plugin

Comprehensive code coverage tool for Scala providing statement and branch coverage through compiler plugin instrumentation and report generation

Pending
Overview
Eval results
Files

coverage-model.mddocs/

Coverage Data Model

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.

Core Data Structures

Coverage Class

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 tracking
  • addIgnoredStatement(stmt: Statement) - Add a statement that should be ignored
  • apply(ids: Iterable[(Int, String)]) - Apply measurement data to mark statements as invoked
  • invoked(id: (Int, String)) - Mark a specific statement as invoked
  • risks(limit: Int) - Get classes with lowest coverage (highest risk)

Statement Class

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 information
  • id - Unique identifier for the statement
  • start - Character offset start position in source file
  • end - Character offset end position in source file
  • line - Line number in source file
  • desc - Human-readable description of the statement
  • symbolName - Scala symbol name (e.g., "scala.Predef.println")
  • treeName - Scala compiler tree type (e.g., "Apply", "Select")
  • branch - Whether this statement represents a branch point
  • count - Number of times statement was executed
  • ignored - Whether statement should be excluded from coverage
  • tests - Set of test names that executed this statement

Location Class

Contains 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 statement
  • className - Simple class name
  • fullClassName - Fully qualified class name
  • classType - Type of class (Class, Object, or Trait)
  • method - Method containing the statement
  • sourcePath - Absolute path to source file

Measured Coverage Types

MeasuredClass

Represents 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 class
  • loc - Lines of code (highest line number with a statement)
  • displayClassName - Class name without package prefix for display

MeasuredMethod

Represents coverage metrics for a single method.

case class MeasuredMethod(
  name: String,
  statements: Iterable[Statement]
) extends CoverageMetrics

Parameters:

  • name - Method name with signature information
  • statements - All statements contained in this method

MeasuredPackage

Represents coverage metrics for a package.

case class MeasuredPackage(
  name: String,
  statements: Iterable[Statement]
) extends CoverageMetrics with ClassCoverage with ClassBuilders with FileBuilders

Parameters:

  • name - Package name (fully qualified)
  • statements - All statements in the package

MeasuredFile

Represents 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 path
  • loc - Lines of code (highest line number with a statement)

Coverage Metrics Trait

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 statements
  • invokedStatementCount - Statements that were executed
  • statementCoverage - 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 points
  • invokedBranchesCount - Branch points that were executed
  • branchCoverage - Branch coverage as decimal (0.0 to 1.0)
  • branchCoveragePercent - Branch coverage as percentage (0.0 to 100.0)
  • branchCoverageFormatted - Formatted branch coverage percentage

Supporting Types

ClassType

Enumeration 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
}

CodeGrid

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 highlighting

StatementStatus

Represents 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 StatementStatus

ClassRef

Utility 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
}

Builder Traits

MethodBuilders

Provides method aggregation functionality.

trait MethodBuilders {
  def statements: Iterable[Statement]
  def methods: Seq[MeasuredMethod]
  def methodCount: Int
}

PackageBuilders

Provides package aggregation functionality.

trait PackageBuilders {
  def statements: Iterable[Statement]
  def packages: Seq[MeasuredPackage]
  def packageCount: Int
}

ClassBuilders

Provides class aggregation functionality.

trait ClassBuilders {
  def statements: Iterable[Statement]
  def classes: Iterable[MeasuredClass]
  def classCount: Int
}

FileBuilders

Provides file aggregation functionality.

trait FileBuilders {
  def statements: Iterable[Statement]
  def files: Iterable[MeasuredFile]
  def fileCount: Int
}

Usage Examples

Creating Coverage Data

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)

Applying Measurement Data

// 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}%")

Analyzing Coverage

// 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}%")
  }
}

Working with Files and Methods

// 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")
  }
}

Error Handling

Data Integrity:

  • Statements with duplicate IDs will overwrite previous statements
  • Invalid coverage data may result in calculation errors
  • Missing measurement data results in 0% coverage

Common Issues:

  • Ensure statement IDs are unique within a coverage instance
  • Verify that measurement data matches existing statement IDs
  • Handle cases where source files may have been moved or deleted

Install with Tessl CLI

npx tessl i tessl/maven-org-scoverage--scalac-scoverage-plugin

docs

aggregation.md

cobertura-reports.md

coverage-model.md

html-reports.md

index.md

io-utils.md

plugin.md

runtime.md

serialization.md

xml-reports.md

tile.json