5561: Allow running more tests at once via the module runners r=matklad a=SomeoneToIgnore

Sometimes I group tests into submodules located in the root `#[cfg(test)]` crate and want to (re)run them all at once.
This PR adds more test runnables to allow running all tests in the file via a module runner.
Not all possible module runners are added, to avoid displaying too many code lens.

before:
<img width="306" alt="before" src="https://user-images.githubusercontent.com/2690773/88724886-e4c6ea00-d133-11ea-9d80-082bb610d422.png">

after (`nested_tests_0` got the runnable, `root_tests` had not):
<img width="300" alt="after" src="https://user-images.githubusercontent.com/2690773/88724896-e85a7100-d133-11ea-99ee-689126679cbc.png">



Co-authored-by: Kirill Bulatov <mail4score@gmail.com>
This commit is contained in:
bors[bot] 2020-07-29 08:39:51 +00:00 committed by GitHub
commit 82e390ff86
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -220,15 +220,7 @@ fn runnable_mod(
module: ast::Module, module: ast::Module,
file_id: FileId, file_id: FileId,
) -> Option<Runnable> { ) -> Option<Runnable> {
let has_test_function = module if !has_test_function_or_multiple_test_submodules(&module) {
.item_list()?
.items()
.filter_map(|it| match it {
ast::ModuleItem::FnDef(it) => Some(it),
_ => None,
})
.any(|f| has_test_related_attribute(&f));
if !has_test_function {
return None; return None;
} }
let module_def = sema.to_def(&module)?; let module_def = sema.to_def(&module)?;
@ -246,6 +238,34 @@ fn runnable_mod(
Some(Runnable { nav, kind: RunnableKind::TestMod { path }, cfg_exprs }) Some(Runnable { nav, kind: RunnableKind::TestMod { path }, cfg_exprs })
} }
// We could create runnables for modules with number_of_test_submodules > 0,
// but that bloats the runnables for no real benefit, since all tests can be run by the submodule already
fn has_test_function_or_multiple_test_submodules(module: &ast::Module) -> bool {
if let Some(item_list) = module.item_list() {
let mut number_of_test_submodules = 0;
for item in item_list.items() {
match item {
ast::ModuleItem::FnDef(f) => {
if has_test_related_attribute(&f) {
return true;
}
}
ast::ModuleItem::Module(submodule) => {
if has_test_function_or_multiple_test_submodules(&submodule) {
number_of_test_submodules += 1;
}
}
_ => (),
}
}
number_of_test_submodules > 1
} else {
false
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use expect::{expect, Expect}; use expect::{expect, Expect};
@ -571,19 +591,33 @@ mod test_mod {
} }
#[test] #[test]
fn test_runnables_one_depth_layer_module() { fn only_modules_with_test_functions_or_more_than_one_test_submodule_have_runners() {
check( check(
r#" r#"
//- /lib.rs //- /lib.rs
<|> <|>
mod foo { mod root_tests {
mod test_mod { mod nested_tests_0 {
mod nested_tests_1 {
#[test] #[test]
fn test_foo1() {} fn nested_test_11() {}
#[test]
fn nested_test_12() {}
} }
mod nested_tests_2 {
#[test]
fn nested_test_2() {}
}
mod nested_tests_3 {}
}
mod nested_tests_4 {}
} }
"#, "#,
&[&TEST, &TEST], &[&TEST, &TEST, &TEST, &TEST, &TEST, &TEST],
expect![[r#" expect![[r#"
[ [
Runnable { Runnable {
@ -591,18 +625,18 @@ mod foo {
file_id: FileId( file_id: FileId(
1, 1,
), ),
full_range: 15..77, full_range: 22..323,
focus_range: Some( focus_range: Some(
19..27, 26..40,
), ),
name: "test_mod", name: "nested_tests_0",
kind: MODULE, kind: MODULE,
container_name: None, container_name: None,
description: None, description: None,
docs: None, docs: None,
}, },
kind: TestMod { kind: TestMod {
path: "foo::test_mod", path: "root_tests::nested_tests_0",
}, },
cfg_exprs: [], cfg_exprs: [],
}, },
@ -611,11 +645,31 @@ mod foo {
file_id: FileId( file_id: FileId(
1, 1,
), ),
full_range: 38..71, full_range: 51..192,
focus_range: Some( focus_range: Some(
57..66, 55..69,
), ),
name: "test_foo1", name: "nested_tests_1",
kind: MODULE,
container_name: None,
description: None,
docs: None,
},
kind: TestMod {
path: "root_tests::nested_tests_0::nested_tests_1",
},
cfg_exprs: [],
},
Runnable {
nav: NavigationTarget {
file_id: FileId(
1,
),
full_range: 84..126,
focus_range: Some(
107..121,
),
name: "nested_test_11",
kind: FN_DEF, kind: FN_DEF,
container_name: None, container_name: None,
description: None, description: None,
@ -623,7 +677,7 @@ mod foo {
}, },
kind: Test { kind: Test {
test_id: Path( test_id: Path(
"foo::test_mod::test_foo1", "root_tests::nested_tests_0::nested_tests_1::nested_test_11",
), ),
attr: TestAttr { attr: TestAttr {
ignore: false, ignore: false,
@ -631,46 +685,28 @@ mod foo {
}, },
cfg_exprs: [], cfg_exprs: [],
}, },
]
"#]],
);
}
#[test]
fn test_runnables_multiple_depth_module() {
check(
r#"
//- /lib.rs
<|>
mod foo {
mod bar {
mod test_mod {
#[test]
fn test_foo1() {}
}
}
}
"#,
&[&TEST, &TEST],
expect![[r#"
[
Runnable { Runnable {
nav: NavigationTarget { nav: NavigationTarget {
file_id: FileId( file_id: FileId(
1, 1,
), ),
full_range: 33..107, full_range: 140..182,
focus_range: Some( focus_range: Some(
37..45, 163..177,
), ),
name: "test_mod", name: "nested_test_12",
kind: MODULE, kind: FN_DEF,
container_name: None, container_name: None,
description: None, description: None,
docs: None, docs: None,
}, },
kind: TestMod { kind: Test {
path: "foo::bar::test_mod", test_id: Path(
"root_tests::nested_tests_0::nested_tests_1::nested_test_12",
),
attr: TestAttr {
ignore: false,
},
}, },
cfg_exprs: [], cfg_exprs: [],
}, },
@ -679,11 +715,31 @@ mod foo {
file_id: FileId( file_id: FileId(
1, 1,
), ),
full_range: 60..97, full_range: 202..286,
focus_range: Some( focus_range: Some(
83..92, 206..220,
), ),
name: "test_foo1", name: "nested_tests_2",
kind: MODULE,
container_name: None,
description: None,
docs: None,
},
kind: TestMod {
path: "root_tests::nested_tests_0::nested_tests_2",
},
cfg_exprs: [],
},
Runnable {
nav: NavigationTarget {
file_id: FileId(
1,
),
full_range: 235..276,
focus_range: Some(
258..271,
),
name: "nested_test_2",
kind: FN_DEF, kind: FN_DEF,
container_name: None, container_name: None,
description: None, description: None,
@ -691,7 +747,7 @@ mod foo {
}, },
kind: Test { kind: Test {
test_id: Path( test_id: Path(
"foo::bar::test_mod::test_foo1", "root_tests::nested_tests_0::nested_tests_2::nested_test_2",
), ),
attr: TestAttr { attr: TestAttr {
ignore: false, ignore: false,