Comprehensive code coverage tool for Scala providing statement and branch coverage through compiler plugin instrumentation and report generation
—
The IOUtils object provides utilities for working with coverage data files, measurement files, and report output. It handles file operations, measurement data loading, and directory management for the scoverage ecosystem.
object IOUtils {
// File operations
def writeToFile(file: File, str: String, encoding: Option[String]): Unit
def readStreamAsString(in: InputStream): String
// Measurement file handling
def findMeasurementFiles(dataDir: File): Array[File]
def findMeasurementFiles(dataDir: String): Array[File]
def measurementFile(dataDir: File): File
def measurementFile(dataDir: String): File
def invoked(files: Seq[File], encoding: String = "UTF-8"): Set[(Int, String)]
// Report file utilities
def reportFile(outputDir: File, debug: Boolean = false): File
// Directory operations
def clean(dataDir: File): Unit
def clean(dataDir: String): Unit
def scoverageDataDirsSearch(baseDir: File): Seq[File]
// Path utilities
def getName(path: String): String
// System utilities
def getTempDirectory: File
def getTempPath: String
}def writeToFile(file: File, str: String, encoding: Option[String]): UnitWrites string content to a file with specified encoding support.
Usage Examples:
import java.io.File
import scoverage.reporter.IOUtils
// Write with UTF-8 encoding
val reportFile = new File("target/report.html")
val htmlContent = "<html><body>Coverage Report</body></html>"
IOUtils.writeToFile(reportFile, htmlContent, Some("UTF-8"))
// Write with default encoding
IOUtils.writeToFile(reportFile, htmlContent, None)
// Write with specific encoding
IOUtils.writeToFile(reportFile, htmlContent, Some("ISO-8859-1"))def readStreamAsString(in: InputStream): StringReads an InputStream completely into a string.
Usage Examples:
import scoverage.reporter.IOUtils
// Read from resource stream
val cssStream = getClass.getResourceAsStream("/scoverage/pure-min.css")
val cssContent = IOUtils.readStreamAsString(cssStream)
cssStream.close()
// Read from file input stream
val fileStream = new FileInputStream("data.txt")
try {
val content = IOUtils.readStreamAsString(fileStream)
println(s"Read ${content.length} characters")
} finally {
fileStream.close()
}def findMeasurementFiles(dataDir: File): Array[File]
def findMeasurementFiles(dataDir: String): Array[File]Locates all measurement files in a scoverage data directory.
Usage Examples:
import java.io.File
import scoverage.reporter.IOUtils
// Find measurement files in directory
val dataDir = new File("target/scoverage-data")
val measurementFiles = IOUtils.findMeasurementFiles(dataDir)
println(s"Found ${measurementFiles.length} measurement files:")
measurementFiles.foreach { file =>
println(s" ${file.getName}")
}
// Using string path
val measurementFiles2 = IOUtils.findMeasurementFiles("target/scoverage-data")def measurementFile(dataDir: File): File
def measurementFile(dataDir: String): FileReturns the measurement file for the current thread.
Usage Examples:
import scoverage.reporter.IOUtils
// Get measurement file for current thread
val dataDir = new File("target/scoverage-data")
val currentThreadFile = IOUtils.measurementFile(dataDir)
println(s"Current thread measurement file: ${currentThreadFile.getName}")
// The file will be named like: scoverage.measurements.12345
// where 12345 is the current thread IDdef invoked(files: Seq[File], encoding: String = "UTF-8"): Set[(Int, String)]Loads invocation data from measurement files, returning statement IDs and test names.
Usage Examples:
import java.io.File
import scoverage.reporter.IOUtils
// Load measurement data from all files
val dataDir = new File("target/scoverage-data")
val measurementFiles = IOUtils.findMeasurementFiles(dataDir)
val measurements = IOUtils.invoked(measurementFiles.toSeq)
println(s"Loaded ${measurements.size} statement invocations")
measurements.take(5).foreach { case (id, testName) =>
if (testName.nonEmpty) {
println(s"Statement $id was invoked by test: $testName")
} else {
println(s"Statement $id was invoked (no test name recorded)")
}
}
// Load with specific encoding
val measurementsLatin1 = IOUtils.invoked(measurementFiles.toSeq, "ISO-8859-1")import scoverage.domain.Coverage
import scoverage.reporter.IOUtils
// Complete workflow: load and apply measurements
val coverage: Coverage = loadCoverageData()
val dataDir = new File("target/scoverage-data")
val measurementFiles = IOUtils.findMeasurementFiles(dataDir)
val measurements = IOUtils.invoked(measurementFiles.toSeq)
// Apply measurements to coverage
coverage.apply(measurements)
println(s"Coverage after applying measurements:")
println(s" Statements: ${coverage.invokedStatementCount}/${coverage.statementCount}")
println(s" Coverage: ${coverage.statementCoverageFormatted}%")def reportFile(outputDir: File, debug: Boolean = false): FileReturns the standard scoverage XML report file path.
Usage Examples:
import java.io.File
import scoverage.reporter.IOUtils
val outputDir = new File("target/scoverage-report")
// Standard report file
val standardReport = IOUtils.reportFile(outputDir, debug = false)
println(s"Standard report: ${standardReport.getName}") // scoverage.xml
// Debug report file
val debugReport = IOUtils.reportFile(outputDir, debug = true)
println(s"Debug report: ${debugReport.getName}") // scoverage-debug.xmldef clean(dataDir: File): Unit
def clean(dataDir: String): UnitRemoves all measurement files from a data directory.
Usage Examples:
import java.io.File
import scoverage.reporter.IOUtils
// Clean measurement files from directory
val dataDir = new File("target/scoverage-data")
println(s"Cleaning measurement files from: ${dataDir.getPath}")
IOUtils.clean(dataDir)
// Clean using string path
IOUtils.clean("target/scoverage-data")
// Clean after generating reports
def generateReportsAndClean(coverage: Coverage): Unit = {
// Generate reports...
generateHtmlReport(coverage)
generateXmlReport(coverage)
// Clean up measurement files
IOUtils.clean("target/scoverage-data")
println("Measurement files cleaned up")
}def scoverageDataDirsSearch(baseDir: File): Seq[File]Recursively searches for scoverage data directories within a base directory.
Usage Examples:
import java.io.File
import scoverage.reporter.IOUtils
// Search for all scoverage data directories in project
val projectRoot = new File(".")
val dataDirs = IOUtils.scoverageDataDirsSearch(projectRoot)
println(s"Found ${dataDirs.size} scoverage data directories:")
dataDirs.foreach { dir =>
println(s" ${dir.getPath}")
}
// Use found directories for aggregation
if (dataDirs.nonEmpty) {
val aggregatedCoverage = CoverageAggregator.aggregatedCoverage(dataDirs, projectRoot)
println(s"Aggregated coverage: ${aggregatedCoverage.statementCoverageFormatted}%")
}def getName(path: String): StringExtracts the filename from a path, handling both Unix and Windows separators.
Usage Examples:
import scoverage.reporter.IOUtils
// Unix-style paths
val unixPath = "/path/to/file.scala"
println(IOUtils.getName(unixPath)) // "file.scala"
// Windows-style paths
val windowsPath = "C:\\path\\to\\file.scala"
println(IOUtils.getName(windowsPath)) // "file.scala"
// Mixed separators
val mixedPath = "/path\\to/file.scala"
println(IOUtils.getName(mixedPath)) // "file.scala"def getTempDirectory: File
def getTempPath: StringAccess to system temporary directory.
Usage Examples:
import scoverage.reporter.IOUtils
// Get temp directory as File
val tempDir = IOUtils.getTempDirectory
println(s"Temp directory: ${tempDir.getPath}")
// Get temp path as String
val tempPath = IOUtils.getTempPath
println(s"Temp path: $tempPath")
// Use for temporary coverage data
val tempCoverageDir = new File(tempDir, "scoverage-temp")
tempCoverageDir.mkdirs()
// ... perform coverage operations ...
// Clean up
tempCoverageDir.delete()import java.io.File
import scoverage.reporter.IOUtils
def processCoverageFiles(rootDir: File): Unit = {
// Find all data directories
val dataDirs = IOUtils.scoverageDataDirsSearch(rootDir)
dataDirs.foreach { dataDir =>
println(s"Processing directory: ${dataDir.getPath}")
// Find and process measurement files
val measurementFiles = IOUtils.findMeasurementFiles(dataDir)
if (measurementFiles.nonEmpty) {
val measurements = IOUtils.invoked(measurementFiles.toSeq)
println(s" Found ${measurements.size} measurement records")
// Process measurements...
} else {
println(s" No measurement files found")
}
}
}import java.io.File
import scoverage.reporter.IOUtils
def writeReportWithFallback(file: File, content: String, preferredEncoding: String): Unit = {
try {
IOUtils.writeToFile(file, content, Some(preferredEncoding))
println(s"Written with $preferredEncoding encoding")
} catch {
case _: java.nio.charset.UnsupportedCharsetException =>
println(s"$preferredEncoding not supported, falling back to UTF-8")
IOUtils.writeToFile(file, content, Some("UTF-8"))
}
}import scoverage.reporter.IOUtils
def readResourceSafely(resourcePath: String): Option[String] = {
Option(getClass.getResourceAsStream(resourcePath)) match {
case Some(stream) =>
try {
Some(IOUtils.readStreamAsString(stream))
} finally {
stream.close()
}
case None =>
println(s"Resource not found: $resourcePath")
None
}
}
// Usage
val cssContent = readResourceSafely("/scoverage/pure-min.css")
cssContent.foreach { css =>
IOUtils.writeToFile(new File("target/pure-min.css"), css, Some("UTF-8"))
}File Permission Errors:
import java.io.IOException
try {
IOUtils.writeToFile(reportFile, content, Some("UTF-8"))
} catch {
case ex: IOException =>
println(s"Failed to write file: ${ex.getMessage}")
// Check directory permissions, create parent directories, etc.
}Encoding Issues:
import java.nio.charset.UnsupportedCharsetException
try {
val measurements = IOUtils.invoked(measurementFiles, "CUSTOM-ENCODING")
} catch {
case ex: UnsupportedCharsetException =>
println(s"Unsupported encoding, using UTF-8: ${ex.getMessage}")
val measurements = IOUtils.invoked(measurementFiles, "UTF-8")
}Missing Directories:
val dataDir = new File("target/scoverage-data")
if (!dataDir.exists()) {
println(s"Data directory does not exist: ${dataDir.getPath}")
} else {
val measurementFiles = IOUtils.findMeasurementFiles(dataDir)
if (measurementFiles.isEmpty) {
println("No measurement files found in directory")
}
}Install with Tessl CLI
npx tessl i tessl/maven-org-scoverage--scalac-scoverage-plugin