diff --git a/crates/forge/bin/cmd/coverage.rs b/crates/forge/bin/cmd/coverage.rs index 70a44aa10878..08173dbaa94e 100644 --- a/crates/forge/bin/cmd/coverage.rs +++ b/crates/forge/bin/cmd/coverage.rs @@ -1,6 +1,6 @@ use super::{install, test::FilterArgs}; use alloy_primitives::{Address, Bytes, U256}; -use clap::{Parser, ValueEnum}; +use clap::{Parser, ValueEnum, ValueHint}; use ethers::{ prelude::{ artifacts::{Ast, CompactBytecode, CompactDeployedBytecode}, @@ -29,7 +29,7 @@ use foundry_common::{compile::ProjectCompiler, evm::EvmArgs, fs}; use foundry_config::{Config, SolcReq}; use foundry_utils::types::ToEthers; use semver::Version; -use std::{collections::HashMap, sync::mpsc::channel}; +use std::{collections::HashMap, path::PathBuf, sync::mpsc::channel}; use tracing::trace; use yansi::Paint; @@ -55,6 +55,17 @@ pub struct CoverageArgs { #[clap(long)] ir_minimum: bool, + /// The path to output the report. + /// + /// If not specified, the report will be stored in the root of the project. + #[clap( + long, + short, + value_hint = ValueHint::FilePath, + value_name = "PATH" + )] + report_file: Option, + #[clap(flatten)] filter: FilterArgs, @@ -342,9 +353,14 @@ impl CoverageArgs { for report_kind in self.report { match report_kind { CoverageReportKind::Summary => SummaryReporter::default().report(&report), - // TODO: Sensible place to put the LCOV file CoverageReportKind::Lcov => { - LcovReporter::new(&mut fs::create_file(root.join("lcov.info"))?).report(&report) + if let Some(report_file) = self.report_file { + return LcovReporter::new(&mut fs::create_file(root.join(report_file))?) + .report(&report) + } else { + return LcovReporter::new(&mut fs::create_file(root.join("lcov.info"))?) + .report(&report) + } } CoverageReportKind::Debug => DebugReporter.report(&report), }?; diff --git a/crates/forge/tests/cli/coverage.rs b/crates/forge/tests/cli/coverage.rs index 05b76a06fdf1..eb950832dfd1 100644 --- a/crates/forge/tests/cli/coverage.rs +++ b/crates/forge/tests/cli/coverage.rs @@ -4,3 +4,13 @@ forgetest!(basic_coverage, |_prj: TestProject, mut cmd: TestCommand| { cmd.args(["coverage"]); cmd.assert_success(); }); + +forgetest!(report_file_coverage, |prj: TestProject, mut cmd: TestCommand| { + cmd.arg("coverage").args([ + "--report".to_string(), + "lcov".to_string(), + "--report-file".to_string(), + prj.root().join("lcov.info").to_str().unwrap().to_string(), + ]); + cmd.assert_success(); +});