Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow multiple test filters #8

Merged
merged 1 commit into from Feb 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
19 changes: 7 additions & 12 deletions src/cli.rs
Expand Up @@ -10,7 +10,7 @@ use super::time::TestTimeOptions;
#[derive(Debug)]
pub struct TestOpts {
pub list: bool,
pub filter: Option<String>,
pub filters: Vec<String>,
pub filter_exact: bool,
pub force_run_in_process: bool,
pub exclude_should_panic: bool,
Expand Down Expand Up @@ -148,12 +148,13 @@ fn optgroups() -> getopts::Options {
}

fn usage(binary: &str, options: &getopts::Options) {
let message = format!("Usage: {} [OPTIONS] [FILTER]", binary);
let message = format!("Usage: {} [OPTIONS] [FILTERS...]", binary);
println!(
r#"{usage}

The FILTER string is tested against the name of all tests, and only those
tests whose names contain the filter are run.
The FILTERS string is tested against the name of all tests, and only those
tests whose names contain the filter are run. Multiple filter strings may
be passed, which will run all tests matching any of the filters.

By default, all tests are run in parallel. This can be altered with the
--test-threads flag or the RUST_TEST_THREADS environment variable when running
Expand Down Expand Up @@ -243,7 +244,7 @@ fn parse_opts_impl(matches: getopts::Matches) -> OptRes {

let logfile = get_log_file(&matches)?;
let run_ignored = get_run_ignored(&matches, include_ignored)?;
let filter = get_filter(&matches)?;
let filters = matches.free.clone();
let nocapture = get_nocapture(&matches)?;
let test_threads = get_test_threads(&matches)?;
let color = get_color_config(&matches)?;
Expand All @@ -253,7 +254,7 @@ fn parse_opts_impl(matches: getopts::Matches) -> OptRes {

let test_opts = TestOpts {
list,
filter,
filters,
filter_exact: exact,
force_run_in_process,
exclude_should_panic,
Expand Down Expand Up @@ -397,12 +398,6 @@ fn get_run_ignored(matches: &getopts::Matches, include_ignored: bool) -> OptPart
Ok(run_ignored)
}

fn get_filter(matches: &getopts::Matches) -> OptPartRes<Option<String>> {
let filter = if !matches.free.is_empty() { Some(matches.free[0].clone()) } else { None };

Ok(filter)
}

fn get_allow_unstable(matches: &getopts::Matches) -> OptPartRes<bool> {
let mut allow_unstable = false;

Expand Down
4 changes: 2 additions & 2 deletions src/lib.rs
Expand Up @@ -359,8 +359,8 @@ pub fn filter_tests(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> Vec<TestDescA
};

// Remove tests that don't match the test filter
if let Some(ref filter) = opts.filter {
filtered.retain(|test| matches_filter(test, filter));
if !opts.filters.is_empty() {
filtered.retain(|test| opts.filters.iter().any(|filter| matches_filter(test, filter)));
}

// Skip tests that match any of the skip filters
Expand Down
34 changes: 25 additions & 9 deletions src/tests.rs
Expand Up @@ -35,7 +35,7 @@ impl TestOpts {
fn new() -> TestOpts {
TestOpts {
list: false,
filter: None,
filters: vec![],
filter_exact: false,
force_run_in_process: false,
exclude_should_panic: false,
Expand Down Expand Up @@ -469,43 +469,59 @@ pub fn exact_filter_match() {
}

let substr =
filter_tests(&TestOpts { filter: Some("base".into()), ..TestOpts::new() }, tests());
filter_tests(&TestOpts { filters: vec!["base".into()], ..TestOpts::new() }, tests());
assert_eq!(substr.len(), 4);

let substr = filter_tests(&TestOpts { filter: Some("bas".into()), ..TestOpts::new() }, tests());
let substr = filter_tests(&TestOpts { filters: vec!["bas".into()], ..TestOpts::new() }, tests());
assert_eq!(substr.len(), 4);

let substr =
filter_tests(&TestOpts { filter: Some("::test".into()), ..TestOpts::new() }, tests());
filter_tests(&TestOpts { filters: vec!["::test".into()], ..TestOpts::new() }, tests());
assert_eq!(substr.len(), 3);

let substr =
filter_tests(&TestOpts { filter: Some("base::test".into()), ..TestOpts::new() }, tests());
filter_tests(&TestOpts { filters: vec!["base::test".into()], ..TestOpts::new() }, tests());
assert_eq!(substr.len(), 3);

let substr = filter_tests(
&TestOpts { filters: vec!["test1".into(), "test2".into()], ..TestOpts::new() },
tests(),
);
assert_eq!(substr.len(), 2);

let exact = filter_tests(
&TestOpts { filter: Some("base".into()), filter_exact: true, ..TestOpts::new() },
&TestOpts { filters: vec!["base".into()], filter_exact: true, ..TestOpts::new() },
tests(),
);
assert_eq!(exact.len(), 1);

let exact = filter_tests(
&TestOpts { filter: Some("bas".into()), filter_exact: true, ..TestOpts::new() },
&TestOpts { filters: vec!["bas".into()], filter_exact: true, ..TestOpts::new() },
tests(),
);
assert_eq!(exact.len(), 0);

let exact = filter_tests(
&TestOpts { filter: Some("::test".into()), filter_exact: true, ..TestOpts::new() },
&TestOpts { filters: vec!["::test".into()], filter_exact: true, ..TestOpts::new() },
tests(),
);
assert_eq!(exact.len(), 0);

let exact = filter_tests(
&TestOpts { filter: Some("base::test".into()), filter_exact: true, ..TestOpts::new() },
&TestOpts { filters: vec!["base::test".into()], filter_exact: true, ..TestOpts::new() },
tests(),
);
assert_eq!(exact.len(), 1);

let exact = filter_tests(
&TestOpts {
filters: vec!["base".into(), "base::test".into()],
filter_exact: true,
..TestOpts::new()
},
tests(),
);
assert_eq!(exact.len(), 2);
}

#[test]
Expand Down