Code coverage for Solidity testing
npx @tessl/cli install tessl/npm-solidity-coverage@0.8.0Solidity Coverage is a comprehensive code coverage analysis tool for Solidity smart contract testing within the Hardhat development environment. It acts as a Hardhat plugin that instruments Solidity contracts to measure statement, function, and modifier coverage during test execution, generating detailed Istanbul coverage reports in multiple formats.
npm install --save-dev solidity-coverageHardhat Plugin (Primary Usage):
require('solidity-coverage');Or with TypeScript:
import 'solidity-coverage';Programmatic API:
const API = require('solidity-coverage/api');Utility Functions:
const utils = require('solidity-coverage/utils');Primary Usage as Hardhat Plugin:
Add the plugin to your hardhat.config.js:
require('solidity-coverage');
module.exports = {
solidity: "0.8.19",
// other config...
};Run coverage analysis:
npx hardhat coverageConfiguration via .solcover.js:
module.exports = {
skipFiles: ['contracts/mocks/'],
istanbulReporter: ['html', 'lcov', 'text'],
measureStatementCoverage: true,
measureFunctionCoverage: true,
measureModifierCoverage: true,
measureLineCoverage: true,
measureBranchCoverage: true,
onServerReady: () => console.log('Coverage server ready'),
onTestsComplete: () => console.log('Tests completed'),
};Solidity Coverage is built around several key components:
Instrumenter class that modifies Solidity source code to inject coverage tracking callsDataCollector class that hooks into Hardhat's EVM to capture execution traces during test runsCoverage class that converts execution data into Istanbul-compatible coverage reports.solcover.js files and CLI options with full validationUI, AppUI, PluginUI) for different output formats and reportingThe primary interface for running coverage analysis within Hardhat projects. Provides the coverage task with extensive configuration options.
npx hardhat coverage [options]
Options:
--testfiles <path> # Glob path to subset of test files
--solcoverjs <path> # Relative path to .solcover.js config file
--temp <path> # Relative path to temp directory for artifacts
--sources <path> # Relative path to contracts directory
--matrix # Generate test matrix data instead of coverage
--abi # Generate human readable ABI listDirect access to the coverage instrumentation and reporting engine for custom workflows and advanced integrations.
const API = require('solidity-coverage/api');
class API {
constructor(config?: CoverageConfig);
instrument(targets: Target[]): InstrumentedTarget[];
report(folder?: string): Promise<void>;
attachToHardhatVM(provider: HardhatProvider): Promise<void>;
// ... additional methods
}
interface Target {
source: string;
canonicalPath: string;
relativePath?: string;
}
interface InstrumentedTarget {
canonicalPath: string;
relativePath?: string;
source: string;
}Helper functions for common coverage-related tasks including file discovery, configuration loading, and temporary directory management.
const utils = require('solidity-coverage/utils');
// File and directory utilities
function assembleFiles(config: Config, skipFiles?: string[]): FileAssembly;
function loadSolcoverJS(config?: Config): CoverageConfig;
function setupTempFolders(config: Config, tempContractsDir: string, tempArtifactsDir: string): void;
// Hardhat integration utilities
function getAccountsHardhat(provider: HardhatProvider): Promise<string[]>;
function finish(config: Config, api: API): Promise<void>;Low-level classes for custom coverage workflows including instrumentation, data collection, and report generation.
const Instrumenter = require('solidity-coverage/lib/instrumenter');
const Coverage = require('solidity-coverage/lib/coverage');
const DataCollector = require('solidity-coverage/lib/collector');
const ConfigValidator = require('solidity-coverage/lib/validator');
const AbiUtils = require('solidity-coverage/lib/abi');
const { UI, AppUI, PluginUI } = require('solidity-coverage/lib/ui');
// Core instrumentation class
class Instrumenter {
constructor(config?: object);
instrument(source: string, canonicalPath: string): InstrumentationResult;
}
// Coverage data management
class Coverage {
constructor();
addContract(info: object, contractPath: string): void;
generate(instrumentationData: object): void;
}interface CoverageConfig {
// File and directory settings
cwd?: string; // Working directory (default: process.cwd())
skipFiles?: string[]; // Files/folders to exclude from coverage
// Server configuration
host?: string; // Server host
port?: number; // Server port
client?: object; // Client configuration
providerOptions?: object; // Provider configuration options
autoLaunchServer?: boolean; // Auto-launch server flag
// Output configuration
istanbulReporter?: string[]; // Report formats: html, lcov, text, json
istanbulFolder?: string; // Output directory for reports
abiOutputPath?: string; // Path for ABI output file
matrixOutputPath?: string; // Path for test matrix output
mochaJsonOutputPath?: string; // Path for Mocha JSON output
matrixReporterPath?: string; // Path to matrix reporter module
// Coverage measurement toggles
measureStatementCoverage?: boolean; // Enable statement coverage (default: true)
measureFunctionCoverage?: boolean; // Enable function coverage (default: true)
measureModifierCoverage?: boolean; // Enable modifier coverage (default: true)
measureLineCoverage?: boolean; // Enable line coverage (default: true)
measureBranchCoverage?: boolean; // Enable branch coverage (default: true)
modifierWhitelist?: string[]; // Specific modifiers to measure
// Compilation settings
viaIR?: boolean; // Enable Solidity viaIR compilation mode
usingSolcV4?: boolean; // Compatibility for Solidity v0.4.x
irMinimum?: boolean; // Use minimal IR optimization
solcOptimizerDetails?: object; // Custom optimizer configuration
// Hook functions for workflow integration
onServerReady?: (config: Config) => void; // Called when coverage server is ready
onCompileComplete?: (config: Config) => void; // Called after compilation
onTestsComplete?: (config: Config) => void; // Called after tests complete
onIstanbulComplete?: (config: Config) => void; // Called after report generation
onPreCompile?: (config: Config) => void; // Called before compilation
// Logging and UI
silent?: boolean; // Disable console output
log?: (message: string) => void; // Custom logging function
// Mocha configuration passthrough
mocha?: object; // Mocha test configuration options
}Solidity Coverage provides detailed error reporting for common issues:
Coverage failures typically throw HardhatPluginError with descriptive messages for debugging.