mirror of
https://github.com/denoland/deno.git
synced 2025-03-03 17:34:47 -05:00
feat(cli/tools/test_runner): add terse reporter (#11156)
This commit adds "--terse" flag to "deno test" that makes testing reporter output one character per test case instead of one line per case. This is an unstable feature.
This commit is contained in:
parent
9b89668065
commit
9d57a4aaeb
6 changed files with 172 additions and 3 deletions
|
@ -100,6 +100,7 @@ pub enum DenoSubcommand {
|
||||||
no_run: bool,
|
no_run: bool,
|
||||||
fail_fast: bool,
|
fail_fast: bool,
|
||||||
quiet: bool,
|
quiet: bool,
|
||||||
|
terse: bool,
|
||||||
allow_none: bool,
|
allow_none: bool,
|
||||||
include: Option<Vec<String>>,
|
include: Option<Vec<String>>,
|
||||||
filter: Option<String>,
|
filter: Option<String>,
|
||||||
|
@ -1010,6 +1011,11 @@ fn test_subcommand<'a, 'b>() -> App<'a, 'b> {
|
||||||
.help("Don't return error code if no test files are found")
|
.help("Don't return error code if no test files are found")
|
||||||
.takes_value(false),
|
.takes_value(false),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("terse")
|
||||||
|
.long("terse")
|
||||||
|
.help("UNSTABLE: Display one character per test instead of one line"),
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("filter")
|
Arg::with_name("filter")
|
||||||
.set(ArgSettings::AllowLeadingHyphen)
|
.set(ArgSettings::AllowLeadingHyphen)
|
||||||
|
@ -1699,6 +1705,7 @@ fn test_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
||||||
let fail_fast = matches.is_present("fail-fast");
|
let fail_fast = matches.is_present("fail-fast");
|
||||||
let allow_none = matches.is_present("allow-none");
|
let allow_none = matches.is_present("allow-none");
|
||||||
let quiet = matches.is_present("quiet");
|
let quiet = matches.is_present("quiet");
|
||||||
|
let terse = matches.is_present("terse");
|
||||||
let filter = matches.value_of("filter").map(String::from);
|
let filter = matches.value_of("filter").map(String::from);
|
||||||
|
|
||||||
let shuffle = if matches.is_present("shuffle") {
|
let shuffle = if matches.is_present("shuffle") {
|
||||||
|
@ -1753,6 +1760,7 @@ fn test_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
||||||
doc,
|
doc,
|
||||||
fail_fast,
|
fail_fast,
|
||||||
quiet,
|
quiet,
|
||||||
|
terse,
|
||||||
include,
|
include,
|
||||||
filter,
|
filter,
|
||||||
shuffle,
|
shuffle,
|
||||||
|
@ -3391,6 +3399,7 @@ mod tests {
|
||||||
filter: Some("- foo".to_string()),
|
filter: Some("- foo".to_string()),
|
||||||
allow_none: true,
|
allow_none: true,
|
||||||
quiet: false,
|
quiet: false,
|
||||||
|
terse: false,
|
||||||
include: Some(svec!["dir1/", "dir2/"]),
|
include: Some(svec!["dir1/", "dir2/"]),
|
||||||
shuffle: None,
|
shuffle: None,
|
||||||
concurrent_jobs: 1,
|
concurrent_jobs: 1,
|
||||||
|
|
|
@ -988,6 +988,7 @@ async fn test_command(
|
||||||
doc: bool,
|
doc: bool,
|
||||||
fail_fast: bool,
|
fail_fast: bool,
|
||||||
quiet: bool,
|
quiet: bool,
|
||||||
|
terse: bool,
|
||||||
allow_none: bool,
|
allow_none: bool,
|
||||||
filter: Option<String>,
|
filter: Option<String>,
|
||||||
shuffle: Option<u64>,
|
shuffle: Option<u64>,
|
||||||
|
@ -1205,6 +1206,7 @@ async fn test_command(
|
||||||
no_run,
|
no_run,
|
||||||
fail_fast,
|
fail_fast,
|
||||||
quiet,
|
quiet,
|
||||||
|
terse,
|
||||||
true,
|
true,
|
||||||
filter.clone(),
|
filter.clone(),
|
||||||
shuffle,
|
shuffle,
|
||||||
|
@ -1243,6 +1245,7 @@ async fn test_command(
|
||||||
no_run,
|
no_run,
|
||||||
fail_fast,
|
fail_fast,
|
||||||
quiet,
|
quiet,
|
||||||
|
terse,
|
||||||
allow_none,
|
allow_none,
|
||||||
filter,
|
filter,
|
||||||
shuffle,
|
shuffle,
|
||||||
|
@ -1350,6 +1353,7 @@ fn get_subcommand(
|
||||||
doc,
|
doc,
|
||||||
fail_fast,
|
fail_fast,
|
||||||
quiet,
|
quiet,
|
||||||
|
terse,
|
||||||
include,
|
include,
|
||||||
allow_none,
|
allow_none,
|
||||||
filter,
|
filter,
|
||||||
|
@ -1362,6 +1366,7 @@ fn get_subcommand(
|
||||||
doc,
|
doc,
|
||||||
fail_fast,
|
fail_fast,
|
||||||
quiet,
|
quiet,
|
||||||
|
terse,
|
||||||
allow_none,
|
allow_none,
|
||||||
filter,
|
filter,
|
||||||
shuffle,
|
shuffle,
|
||||||
|
|
|
@ -49,6 +49,12 @@ itest!(doc {
|
||||||
output: "test/doc.out",
|
output: "test/doc.out",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
itest!(terse {
|
||||||
|
args: "test --terse test/terse.ts",
|
||||||
|
exit_code: 1,
|
||||||
|
output: "test/terse.out",
|
||||||
|
});
|
||||||
|
|
||||||
itest!(quiet {
|
itest!(quiet {
|
||||||
args: "test --quiet test/quiet.ts",
|
args: "test --quiet test/quiet.ts",
|
||||||
exit_code: 0,
|
exit_code: 0,
|
||||||
|
|
11
cli/tests/test/terse.out
Normal file
11
cli/tests/test/terse.out
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
Check [WILDCARD]/test/terse.ts
|
||||||
|
running 3 tests from [WILDCARD]
|
||||||
|
.Fi
|
||||||
|
failures:
|
||||||
|
|
||||||
|
fail
|
||||||
|
Error: fail
|
||||||
|
[WILDCARD]
|
||||||
|
|
||||||
|
test result: FAILED. 1 passed; 1 failed; 1 ignored; 0 measured; 0 filtered out [WILDCARD]
|
||||||
|
|
11
cli/tests/test/terse.ts
Normal file
11
cli/tests/test/terse.ts
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
Deno.test("ok", function () {});
|
||||||
|
|
||||||
|
Deno.test("fail", function () {
|
||||||
|
throw new Error("fail");
|
||||||
|
});
|
||||||
|
|
||||||
|
Deno.test({
|
||||||
|
name: "ignore",
|
||||||
|
fn() {},
|
||||||
|
ignore: true,
|
||||||
|
});
|
|
@ -202,8 +202,128 @@ impl TestReporter for PrettyTestReporter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_reporter(concurrent: bool) -> Box<dyn TestReporter + Send> {
|
struct TerseTestReporter {
|
||||||
Box::new(PrettyTestReporter::new(concurrent))
|
time: Instant,
|
||||||
|
failed: usize,
|
||||||
|
filtered_out: usize,
|
||||||
|
ignored: usize,
|
||||||
|
passed: usize,
|
||||||
|
measured: usize,
|
||||||
|
pending: usize,
|
||||||
|
failures: Vec<(String, String)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TerseTestReporter {
|
||||||
|
fn new() -> TerseTestReporter {
|
||||||
|
TerseTestReporter {
|
||||||
|
time: Instant::now(),
|
||||||
|
failed: 0,
|
||||||
|
filtered_out: 0,
|
||||||
|
ignored: 0,
|
||||||
|
passed: 0,
|
||||||
|
measured: 0,
|
||||||
|
pending: 0,
|
||||||
|
failures: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestReporter for TerseTestReporter {
|
||||||
|
fn visit_event(&mut self, event: TestEvent) {
|
||||||
|
match &event.message {
|
||||||
|
TestMessage::Plan {
|
||||||
|
pending,
|
||||||
|
filtered,
|
||||||
|
only: _,
|
||||||
|
} => {
|
||||||
|
if *pending == 1 {
|
||||||
|
println!("running {} test from {}", pending, event.origin);
|
||||||
|
} else {
|
||||||
|
println!("running {} tests from {}", pending, event.origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.pending += pending;
|
||||||
|
self.filtered_out += filtered;
|
||||||
|
}
|
||||||
|
|
||||||
|
TestMessage::Result {
|
||||||
|
name,
|
||||||
|
duration: _,
|
||||||
|
result,
|
||||||
|
} => {
|
||||||
|
self.pending -= 1;
|
||||||
|
|
||||||
|
match result {
|
||||||
|
TestResult::Ok => {
|
||||||
|
print!("{}", colors::green("."),);
|
||||||
|
|
||||||
|
self.passed += 1;
|
||||||
|
}
|
||||||
|
TestResult::Ignored => {
|
||||||
|
print!("{}", colors::yellow("i"),);
|
||||||
|
|
||||||
|
self.ignored += 1;
|
||||||
|
}
|
||||||
|
TestResult::Failed(error) => {
|
||||||
|
print!("{}", colors::red("F"),);
|
||||||
|
|
||||||
|
self.failed += 1;
|
||||||
|
self.failures.push((name.to_string(), error.to_string()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn done(&mut self) {
|
||||||
|
if !self.failures.is_empty() {
|
||||||
|
println!("\nfailures:\n");
|
||||||
|
for (name, error) in &self.failures {
|
||||||
|
println!("{}", name);
|
||||||
|
println!("{}", error);
|
||||||
|
println!();
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("failures:\n");
|
||||||
|
for (name, _) in &self.failures {
|
||||||
|
println!("\t{}", name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let status = if self.pending > 0 || !self.failures.is_empty() {
|
||||||
|
colors::red("FAILED").to_string()
|
||||||
|
} else {
|
||||||
|
colors::green("ok").to_string()
|
||||||
|
};
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"\ntest result: {}. {} passed; {} failed; {} ignored; {} measured; {} filtered out {}\n",
|
||||||
|
status,
|
||||||
|
self.passed,
|
||||||
|
self.failed,
|
||||||
|
self.ignored,
|
||||||
|
self.measured,
|
||||||
|
self.filtered_out,
|
||||||
|
colors::gray(format!("({}ms)", self.time.elapsed().as_millis())),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum TestReporterKind {
|
||||||
|
Pretty,
|
||||||
|
Terse,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_reporter(
|
||||||
|
kind: TestReporterKind,
|
||||||
|
concurrent: bool,
|
||||||
|
) -> Box<dyn TestReporter + Send> {
|
||||||
|
match kind {
|
||||||
|
TestReporterKind::Pretty => Box::new(PrettyTestReporter::new(concurrent)),
|
||||||
|
TestReporterKind::Terse => Box::new(TerseTestReporter::new()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn is_supported(p: &Path) -> bool {
|
pub(crate) fn is_supported(p: &Path) -> bool {
|
||||||
|
@ -344,6 +464,7 @@ pub async fn run_tests(
|
||||||
no_run: bool,
|
no_run: bool,
|
||||||
fail_fast: bool,
|
fail_fast: bool,
|
||||||
quiet: bool,
|
quiet: bool,
|
||||||
|
terse: bool,
|
||||||
allow_none: bool,
|
allow_none: bool,
|
||||||
filter: Option<String>,
|
filter: Option<String>,
|
||||||
shuffle: Option<u64>,
|
shuffle: Option<u64>,
|
||||||
|
@ -510,7 +631,13 @@ pub async fn run_tests(
|
||||||
.buffer_unordered(concurrent_jobs)
|
.buffer_unordered(concurrent_jobs)
|
||||||
.collect::<Vec<Result<Result<(), AnyError>, tokio::task::JoinError>>>();
|
.collect::<Vec<Result<Result<(), AnyError>, tokio::task::JoinError>>>();
|
||||||
|
|
||||||
let mut reporter = create_reporter(concurrent_jobs > 1);
|
let reporter_kind = if terse {
|
||||||
|
TestReporterKind::Terse
|
||||||
|
} else {
|
||||||
|
TestReporterKind::Pretty
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut reporter = create_reporter(reporter_kind, concurrent_jobs > 1);
|
||||||
let handler = {
|
let handler = {
|
||||||
tokio::task::spawn_blocking(move || {
|
tokio::task::spawn_blocking(move || {
|
||||||
let mut used_only = false;
|
let mut used_only = false;
|
||||||
|
|
Loading…
Add table
Reference in a new issue