Skip to content

Commit

Permalink
Support giving a reason to inconclusive/ignored cases
Browse files Browse the repository at this point in the history
Since Rust 1.61.0 `cargo test` has included the reason string in the output.

The new syntax is optional, so `inconclusive` is still accepted, a reason may
be given inside optional brackets `inconclusive["some reason"]`. Parentheses
are not used to avoid ambiguity with the output/result.

A custom `impl Debug` is used to avoid injecting an unsightly
`inconclusivewithreason_litstr_token` into the test name by default.

Fixes: frondeus#102
  • Loading branch information
ijc committed Jul 20, 2022
1 parent ec22223 commit e911d39
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 7 deletions.
33 changes: 29 additions & 4 deletions crates/test-case-macros/src/modifier.rs
Original file line number Diff line number Diff line change
@@ -1,35 +1,60 @@
use std::collections::HashSet;
use std::fmt::{Debug, Formatter};
use syn::parse::{Parse, ParseStream};
use syn::{parse_quote, Attribute};
use syn::token::Bracket;
use syn::{bracketed, parse_quote, Attribute, LitStr};

mod kw {
syn::custom_keyword!(inconclusive);
syn::custom_keyword!(ignore);
}

#[derive(Debug, PartialEq, Eq, Hash)]
#[derive(PartialEq, Eq, Hash)]
pub enum Modifier {
Inconclusive,
InconclusiveWithReason(LitStr),
}

impl Debug for Modifier {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Modifier::Inconclusive | Modifier::InconclusiveWithReason(_) => {
write!(f, "inconclusive")
}
}
}
}

impl Parse for Modifier {
fn parse(input: ParseStream) -> syn::Result<Self> {
if input.peek(kw::inconclusive) {
let _: kw::inconclusive = input.parse()?;
Ok(Self::Inconclusive)
Self::parse_inconclusive(input)
} else if input.peek(kw::ignore) {
let _: kw::ignore = input.parse()?;
Ok(Self::Inconclusive)
Self::parse_inconclusive(input)
} else {
Err(syn::Error::new(input.span(), "unknown modifier keyword"))
}
}
}

impl Modifier {
pub fn parse_inconclusive(input: ParseStream) -> syn::Result<Self> {
if input.peek(Bracket) {
let content;
let _: Bracket = bracketed!(content in input);
let reason: LitStr = content.parse()?;
Ok(Self::InconclusiveWithReason(reason))
} else {
Ok(Self::Inconclusive)
}
}

pub fn attribute(&self) -> Attribute {
match self {
Modifier::Inconclusive => parse_quote! { #[ignore] },
Modifier::InconclusiveWithReason(r) => parse_quote! { #[ignore = #r] },
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions tests/acceptance_cases/cases_can_be_ignored/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,10 @@ fn inconclusives(_: ()) {
fn ignore_void(input: u8) {
assert_eq!(input, 1)
}

#[test_case(() => inconclusive["reason but no comment"] ())]
#[test_case(() => inconclusive["reason and comment"] (); "test is not run")]
#[test_case(() => ignore["reason and comment"] (); "ignore keyword")]
fn descriptions(_: ()) {
unreachable!()
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
---
source: tests/acceptance_tests.rs
assertion_line: 88
expression: output
---
running 6 tests
running 9 tests
test descriptions::_expects_inconclusive_ ... ignored, reason but no comment
test descriptions::ignore_keyword ... ignored, reason and comment
test descriptions::test_is_not_run ... ignored, reason and comment
test ignore_void::_1_expects_inconclusiveempty ... ignored
test ignore_void::_2_expects_inconclusiveempty ... ignored
test inconclusives::_expects_inconclusive_ ... ignored
test inconclusives::ignore_keyword ... ignored
test inconclusives::inconclusive_test ... ignored
test inconclusives::test_is_not_ran ... ignored
test result: ok. 0 passed; 0 failed; 6 ignored; 0 measured; 0 filtered out; finished in 0.00s
test result: ok. 0 passed; 0 failed; 9 ignored; 0 measured; 0 filtered out; finished in 0.00s

0 comments on commit e911d39

Please sign in to comment.