1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-25 15:29:32 -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:
Casper Beyer 2021-07-10 07:29:18 +08:00 committed by GitHub
parent 9b89668065
commit 9d57a4aaeb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 172 additions and 3 deletions

View file

@ -100,6 +100,7 @@ pub enum DenoSubcommand {
no_run: bool,
fail_fast: bool,
quiet: bool,
terse: bool,
allow_none: bool,
include: Option<Vec<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")
.takes_value(false),
)
.arg(
Arg::with_name("terse")
.long("terse")
.help("UNSTABLE: Display one character per test instead of one line"),
)
.arg(
Arg::with_name("filter")
.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 allow_none = matches.is_present("allow-none");
let quiet = matches.is_present("quiet");
let terse = matches.is_present("terse");
let filter = matches.value_of("filter").map(String::from);
let shuffle = if matches.is_present("shuffle") {
@ -1753,6 +1760,7 @@ fn test_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
doc,
fail_fast,
quiet,
terse,
include,
filter,
shuffle,
@ -3391,6 +3399,7 @@ mod tests {
filter: Some("- foo".to_string()),
allow_none: true,
quiet: false,
terse: false,
include: Some(svec!["dir1/", "dir2/"]),
shuffle: None,
concurrent_jobs: 1,

View file

@ -988,6 +988,7 @@ async fn test_command(
doc: bool,
fail_fast: bool,
quiet: bool,
terse: bool,
allow_none: bool,
filter: Option<String>,
shuffle: Option<u64>,
@ -1205,6 +1206,7 @@ async fn test_command(
no_run,
fail_fast,
quiet,
terse,
true,
filter.clone(),
shuffle,
@ -1243,6 +1245,7 @@ async fn test_command(
no_run,
fail_fast,
quiet,
terse,
allow_none,
filter,
shuffle,
@ -1350,6 +1353,7 @@ fn get_subcommand(
doc,
fail_fast,
quiet,
terse,
include,
allow_none,
filter,
@ -1362,6 +1366,7 @@ fn get_subcommand(
doc,
fail_fast,
quiet,
terse,
allow_none,
filter,
shuffle,

View file

@ -49,6 +49,12 @@ itest!(doc {
output: "test/doc.out",
});
itest!(terse {
args: "test --terse test/terse.ts",
exit_code: 1,
output: "test/terse.out",
});
itest!(quiet {
args: "test --quiet test/quiet.ts",
exit_code: 0,

11
cli/tests/test/terse.out Normal file
View 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
View file

@ -0,0 +1,11 @@
Deno.test("ok", function () {});
Deno.test("fail", function () {
throw new Error("fail");
});
Deno.test({
name: "ignore",
fn() {},
ignore: true,
});

View file

@ -202,8 +202,128 @@ impl TestReporter for PrettyTestReporter {
}
}
fn create_reporter(concurrent: bool) -> Box<dyn TestReporter + Send> {
Box::new(PrettyTestReporter::new(concurrent))
struct TerseTestReporter {
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 {
@ -344,6 +464,7 @@ pub async fn run_tests(
no_run: bool,
fail_fast: bool,
quiet: bool,
terse: bool,
allow_none: bool,
filter: Option<String>,
shuffle: Option<u64>,
@ -510,7 +631,13 @@ pub async fn run_tests(
.buffer_unordered(concurrent_jobs)
.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 = {
tokio::task::spawn_blocking(move || {
let mut used_only = false;