diff --git a/cli/args/flags.rs b/cli/args/flags.rs index 1c18ce00fe..2559cf0a18 100644 --- a/cli/args/flags.rs +++ b/cli/args/flags.rs @@ -333,6 +333,7 @@ pub struct TestFlags { pub doc: bool, pub no_run: bool, pub coverage_dir: Option, + pub clean: bool, pub fail_fast: Option, pub files: FileFlags, pub allow_none: bool, @@ -2630,6 +2631,14 @@ Directory arguments are expanded to all contained files matching the glob .conflicts_with("inspect-brk") .help("Collect coverage profile data into DIR. If DIR is not specified, it uses 'coverage/'."), ) + .arg( + Arg::new("clean") + .long("clean") + .help("Empty the temporary coverage profile data directory before running tests. + +Note: running multiple `deno test --clean` calls in series or parallel for the same coverage directory may cause race conditions.") + .action(ArgAction::SetTrue), + ) .arg( Arg::new("parallel") .long("parallel") @@ -4240,6 +4249,7 @@ fn test_parse(flags: &mut Flags, matches: &mut ArgMatches) { let doc = matches.get_flag("doc"); let allow_none = matches.get_flag("allow-none"); let filter = matches.remove_one::("filter"); + let clean = matches.get_flag("clean"); let fail_fast = if matches.contains_id("fail-fast") { Some( @@ -4325,6 +4335,7 @@ fn test_parse(flags: &mut Flags, matches: &mut ArgMatches) { no_run, doc, coverage_dir: matches.remove_one::("coverage"), + clean, fail_fast, files: FileFlags { include, ignore }, filter, @@ -8189,7 +8200,7 @@ mod tests { #[test] fn test_with_flags() { #[rustfmt::skip] - let r = flags_from_vec(svec!["deno", "test", "--unstable", "--no-npm", "--no-remote", "--trace-leaks", "--no-run", "--filter", "- foo", "--coverage=cov", "--location", "https:foo", "--allow-net", "--allow-none", "dir1/", "dir2/", "--", "arg1", "arg2"]); + let r = flags_from_vec(svec!["deno", "test", "--unstable", "--no-npm", "--no-remote", "--trace-leaks", "--no-run", "--filter", "- foo", "--coverage=cov", "--clean", "--location", "https:foo", "--allow-net", "--allow-none", "dir1/", "dir2/", "--", "arg1", "arg2"]); assert_eq!( r.unwrap(), Flags { @@ -8207,6 +8218,7 @@ mod tests { concurrent_jobs: None, trace_leaks: true, coverage_dir: Some("cov".to_string()), + clean: true, watch: Default::default(), reporter: Default::default(), junit_path: None, @@ -8294,6 +8306,7 @@ mod tests { concurrent_jobs: Some(NonZeroUsize::new(4).unwrap()), trace_leaks: false, coverage_dir: None, + clean: false, watch: Default::default(), junit_path: None, }), @@ -8330,6 +8343,7 @@ mod tests { concurrent_jobs: None, trace_leaks: false, coverage_dir: None, + clean: false, watch: Default::default(), reporter: Default::default(), junit_path: None, @@ -8371,6 +8385,7 @@ mod tests { concurrent_jobs: None, trace_leaks: false, coverage_dir: None, + clean: false, watch: Default::default(), reporter: Default::default(), junit_path: None, @@ -8506,6 +8521,7 @@ mod tests { concurrent_jobs: None, trace_leaks: false, coverage_dir: None, + clean: false, watch: Default::default(), reporter: Default::default(), junit_path: None, @@ -8540,6 +8556,7 @@ mod tests { concurrent_jobs: None, trace_leaks: false, coverage_dir: None, + clean: false, watch: Some(Default::default()), reporter: Default::default(), junit_path: None, @@ -8573,6 +8590,7 @@ mod tests { concurrent_jobs: None, trace_leaks: false, coverage_dir: None, + clean: false, watch: Some(Default::default()), reporter: Default::default(), junit_path: None, @@ -8608,6 +8626,7 @@ mod tests { concurrent_jobs: None, trace_leaks: false, coverage_dir: None, + clean: false, watch: Some(WatchFlags { hmr: false, no_clear_screen: true, diff --git a/cli/main.rs b/cli/main.rs index 44e9d31fd5..a2d270d401 100644 --- a/cli/main.rs +++ b/cli/main.rs @@ -191,6 +191,9 @@ async fn run_subcommand(flags: Flags) -> Result { DenoSubcommand::Test(test_flags) => { spawn_subcommand(async { if let Some(ref coverage_dir) = test_flags.coverage_dir { + if test_flags.clean { + let _ = std::fs::remove_dir_all(coverage_dir); + } std::fs::create_dir_all(coverage_dir) .with_context(|| format!("Failed creating: {coverage_dir}"))?; // this is set in order to ensure spawned processes use the same diff --git a/tests/specs/test/clean_flag/__test__.jsonc b/tests/specs/test/clean_flag/__test__.jsonc new file mode 100644 index 0000000000..65ad097b18 --- /dev/null +++ b/tests/specs/test/clean_flag/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run -A main.js", + "exitCode": 0, + "output": "main.out" +} diff --git a/tests/specs/test/clean_flag/main.js b/tests/specs/test/clean_flag/main.js new file mode 100644 index 0000000000..215c2229c5 --- /dev/null +++ b/tests/specs/test/clean_flag/main.js @@ -0,0 +1,23 @@ +import { emptyDir } from "../../../util/std/fs/empty_dir.ts"; + +const DIR = "./coverage"; +const COMMAND = new Deno.Command(Deno.execPath(), { + args: ["test", "--coverage", "--clean"], + stdout: "null", +}); + +async function getCoverageFiles() { + return await Array.fromAsync(Deno.readDir(DIR), ({ name }) => name); +} + +await emptyDir(DIR); +await COMMAND.output(); +const files1 = new Set(await getCoverageFiles()); + +await COMMAND.output(); +const files2 = new Set(await getCoverageFiles()); + +console.log(files1.size === files2.size); +console.log(files1.intersection(files2).size === 0); +await emptyDir(DIR); +await Deno.remove(DIR); diff --git a/tests/specs/test/clean_flag/main.out b/tests/specs/test/clean_flag/main.out new file mode 100644 index 0000000000..bb101b641b --- /dev/null +++ b/tests/specs/test/clean_flag/main.out @@ -0,0 +1,2 @@ +true +true diff --git a/tests/specs/test/clean_flag/sum.js b/tests/specs/test/clean_flag/sum.js new file mode 100644 index 0000000000..506a413438 --- /dev/null +++ b/tests/specs/test/clean_flag/sum.js @@ -0,0 +1,3 @@ +export function sum(a, b) { + return a + b; +} diff --git a/tests/specs/test/clean_flag/sum_test.js b/tests/specs/test/clean_flag/sum_test.js new file mode 100644 index 0000000000..3443fcbd3f --- /dev/null +++ b/tests/specs/test/clean_flag/sum_test.js @@ -0,0 +1,6 @@ +import { sum } from "./sum.js"; +import { assertEquals } from "../../../util/std/assert/assert_equals.ts"; + +Deno.test("sum()", () => { + assertEquals(sum(1, 2), 3); +});