From 0e4d6d41ad64b89ab72d87a778d1bf3e516efabc Mon Sep 17 00:00:00 2001 From: Cooper Benson Date: Wed, 26 Jul 2023 16:12:35 -0600 Subject: feat(cli): Adding JUnit test reports (#19747) This commit makes the following changes - Created a `CompoundTestReporter` to allow us to use multiple reporters - Implements `JUnitTestReporter` which writes JUnit XML to a path - Added a CLI flag/option `--junit` that enables JUnit reporting. By default this writes the report to `stdout` (and disables pretty reporting). If a path is provided, it will write the JUnit report to that file while the pretty reporter writes to stdout like normal Output of `deno -- test --allow-all --unstable --location=http://js-unit-tests/foo/bar --junit cli/tests/unit/testing_test.ts ` ```xml ``` --- cli/args/flags.rs | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ cli/args/mod.rs | 2 ++ 2 files changed, 84 insertions(+) (limited to 'cli/args') diff --git a/cli/args/flags.rs b/cli/args/flags.rs index d06a17a06..3f4498dac 100644 --- a/cli/args/flags.rs +++ b/cli/args/flags.rs @@ -221,6 +221,7 @@ pub struct TestFlags { pub concurrent_jobs: Option, pub trace_ops: bool, pub watch: Option, + pub junit_path: Option, } #[derive(Clone, Debug, Eq, PartialEq)] @@ -1848,6 +1849,16 @@ Directory arguments are expanded to all contained files matching the glob ) .arg(no_clear_screen_arg()) .arg(script_arg().last(true)) + .arg( + Arg::new("junit") + .long("junit") + .value_name("PATH") + .value_hint(ValueHint::FilePath) + .help("Write a JUnit XML test report to PATH. Use '-' to write to stdout which is the default when PATH is not provided.") + .num_args(0..=1) + .require_equals(true) + .default_missing_value("-") + ) ) } @@ -3034,6 +3045,8 @@ fn test_parse(flags: &mut Flags, matches: &mut ArgMatches) { Vec::new() }; + let junit_path = matches.remove_one::("junit"); + flags.subcommand = DenoSubcommand::Test(TestFlags { no_run, doc, @@ -3046,6 +3059,7 @@ fn test_parse(flags: &mut Flags, matches: &mut ArgMatches) { concurrent_jobs, trace_ops, watch: watch_arg_parse(matches), + junit_path, }); } @@ -5910,6 +5924,7 @@ mod tests { trace_ops: true, coverage_dir: Some("cov".to_string()), watch: Default::default(), + junit_path: None, }), unstable: true, no_prompt: true, @@ -5988,6 +6003,7 @@ mod tests { trace_ops: false, coverage_dir: None, watch: Default::default(), + junit_path: None, }), type_check_mode: TypeCheckMode::Local, no_prompt: true, @@ -6020,6 +6036,7 @@ mod tests { trace_ops: false, coverage_dir: None, watch: Default::default(), + junit_path: None, }), type_check_mode: TypeCheckMode::Local, no_prompt: true, @@ -6056,6 +6073,7 @@ mod tests { trace_ops: false, coverage_dir: None, watch: Default::default(), + junit_path: None, }), no_prompt: true, type_check_mode: TypeCheckMode::Local, @@ -6086,6 +6104,7 @@ mod tests { trace_ops: false, coverage_dir: None, watch: Default::default(), + junit_path: None, }), no_prompt: true, type_check_mode: TypeCheckMode::Local, @@ -6117,6 +6136,7 @@ mod tests { watch: Some(WatchFlags { no_clear_screen: false, }), + junit_path: None, }), no_prompt: true, type_check_mode: TypeCheckMode::Local, @@ -6147,6 +6167,7 @@ mod tests { watch: Some(WatchFlags { no_clear_screen: false, }), + junit_path: None, }), no_prompt: true, type_check_mode: TypeCheckMode::Local, @@ -6179,6 +6200,67 @@ mod tests { watch: Some(WatchFlags { no_clear_screen: true, }), + junit_path: None, + }), + type_check_mode: TypeCheckMode::Local, + no_prompt: true, + ..Flags::default() + } + ); + } + + #[test] + fn test_junit_default() { + let r = flags_from_vec(svec!["deno", "test", "--junit"]); + assert_eq!( + r.unwrap(), + Flags { + subcommand: DenoSubcommand::Test(TestFlags { + no_run: false, + doc: false, + fail_fast: None, + filter: None, + allow_none: false, + shuffle: None, + files: FileFlags { + include: vec![], + ignore: vec![], + }, + concurrent_jobs: None, + trace_ops: false, + coverage_dir: None, + watch: Default::default(), + junit_path: Some("-".to_string()), + }), + type_check_mode: TypeCheckMode::Local, + no_prompt: true, + ..Flags::default() + } + ); + } + + #[test] + fn test_junit_with_path() { + let r = flags_from_vec(svec!["deno", "test", "--junit=junit.xml"]); + assert_eq!( + r.unwrap(), + Flags { + subcommand: DenoSubcommand::Test(TestFlags { + no_run: false, + doc: false, + fail_fast: None, + filter: None, + allow_none: false, + shuffle: None, + files: FileFlags { + include: vec![], + ignore: vec![], + }, + concurrent_jobs: None, + trace_ops: false, + coverage_dir: None, + watch: Default::default(), + junit_path: Some("junit.xml".to_string()), }), type_check_mode: TypeCheckMode::Local, no_prompt: true, diff --git a/cli/args/mod.rs b/cli/args/mod.rs index 9a6050347..a979aa10c 100644 --- a/cli/args/mod.rs +++ b/cli/args/mod.rs @@ -227,6 +227,7 @@ pub struct TestOptions { pub shuffle: Option, pub concurrent_jobs: NonZeroUsize, pub trace_ops: bool, + pub junit_path: Option, } impl TestOptions { @@ -251,6 +252,7 @@ impl TestOptions { no_run: test_flags.no_run, shuffle: test_flags.shuffle, trace_ops: test_flags.trace_ops, + junit_path: test_flags.junit_path, }) } } -- cgit v1.2.3