diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-07-29 09:39:51 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2020-07-29 09:39:51 +0100 |
commit | 82e390ff8687038740b3d3bcfa6c69441ad0be0c (patch) | |
tree | dbe2f77a15554846b9a053d59b517acea77e75d4 /crates/ra_ide | |
parent | 5a8124273dd663f7f1ed43b53defc4a2c52dbc12 (diff) | |
parent | bb1ae85ed0bdd854029435ac5a9f175e3f33e2e7 (diff) |
Merge #5561
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 <[email protected]>
Diffstat (limited to 'crates/ra_ide')
-rw-r--r-- | crates/ra_ide/src/runnables.rs | 164 |
1 files changed, 110 insertions, 54 deletions
diff --git a/crates/ra_ide/src/runnables.rs b/crates/ra_ide/src/runnables.rs index 95a35a28d..45e0a7d85 100644 --- a/crates/ra_ide/src/runnables.rs +++ b/crates/ra_ide/src/runnables.rs | |||
@@ -220,15 +220,7 @@ fn runnable_mod( | |||
220 | module: ast::Module, | 220 | module: ast::Module, |
221 | file_id: FileId, | 221 | file_id: FileId, |
222 | ) -> Option<Runnable> { | 222 | ) -> Option<Runnable> { |
223 | let has_test_function = module | 223 | if !has_test_function_or_multiple_test_submodules(&module) { |
224 | .item_list()? | ||
225 | .items() | ||
226 | .filter_map(|it| match it { | ||
227 | ast::ModuleItem::FnDef(it) => Some(it), | ||
228 | _ => None, | ||
229 | }) | ||
230 | .any(|f| has_test_related_attribute(&f)); | ||
231 | if !has_test_function { | ||
232 | return None; | 224 | return None; |
233 | } | 225 | } |
234 | let module_def = sema.to_def(&module)?; | 226 | let module_def = sema.to_def(&module)?; |
@@ -246,6 +238,34 @@ fn runnable_mod( | |||
246 | Some(Runnable { nav, kind: RunnableKind::TestMod { path }, cfg_exprs }) | 238 | Some(Runnable { nav, kind: RunnableKind::TestMod { path }, cfg_exprs }) |
247 | } | 239 | } |
248 | 240 | ||
241 | // We could create runnables for modules with number_of_test_submodules > 0, | ||
242 | // but that bloats the runnables for no real benefit, since all tests can be run by the submodule already | ||
243 | fn has_test_function_or_multiple_test_submodules(module: &ast::Module) -> bool { | ||
244 | if let Some(item_list) = module.item_list() { | ||
245 | let mut number_of_test_submodules = 0; | ||
246 | |||
247 | for item in item_list.items() { | ||
248 | match item { | ||
249 | ast::ModuleItem::FnDef(f) => { | ||
250 | if has_test_related_attribute(&f) { | ||
251 | return true; | ||
252 | } | ||
253 | } | ||
254 | ast::ModuleItem::Module(submodule) => { | ||
255 | if has_test_function_or_multiple_test_submodules(&submodule) { | ||
256 | number_of_test_submodules += 1; | ||
257 | } | ||
258 | } | ||
259 | _ => (), | ||
260 | } | ||
261 | } | ||
262 | |||
263 | number_of_test_submodules > 1 | ||
264 | } else { | ||
265 | false | ||
266 | } | ||
267 | } | ||
268 | |||
249 | #[cfg(test)] | 269 | #[cfg(test)] |
250 | mod tests { | 270 | mod tests { |
251 | use expect::{expect, Expect}; | 271 | use expect::{expect, Expect}; |
@@ -571,19 +591,33 @@ mod test_mod { | |||
571 | } | 591 | } |
572 | 592 | ||
573 | #[test] | 593 | #[test] |
574 | fn test_runnables_one_depth_layer_module() { | 594 | fn only_modules_with_test_functions_or_more_than_one_test_submodule_have_runners() { |
575 | check( | 595 | check( |
576 | r#" | 596 | r#" |
577 | //- /lib.rs | 597 | //- /lib.rs |
578 | <|> | 598 | <|> |
579 | mod foo { | 599 | mod root_tests { |
580 | mod test_mod { | 600 | mod nested_tests_0 { |
581 | #[test] | 601 | mod nested_tests_1 { |
582 | fn test_foo1() {} | 602 | #[test] |
603 | fn nested_test_11() {} | ||
604 | |||
605 | #[test] | ||
606 | fn nested_test_12() {} | ||
607 | } | ||
608 | |||
609 | mod nested_tests_2 { | ||
610 | #[test] | ||
611 | fn nested_test_2() {} | ||
612 | } | ||
613 | |||
614 | mod nested_tests_3 {} | ||
583 | } | 615 | } |
616 | |||
617 | mod nested_tests_4 {} | ||
584 | } | 618 | } |
585 | "#, | 619 | "#, |
586 | &[&TEST, &TEST], | 620 | &[&TEST, &TEST, &TEST, &TEST, &TEST, &TEST], |
587 | expect![[r#" | 621 | expect![[r#" |
588 | [ | 622 | [ |
589 | Runnable { | 623 | Runnable { |
@@ -591,18 +625,18 @@ mod foo { | |||
591 | file_id: FileId( | 625 | file_id: FileId( |
592 | 1, | 626 | 1, |
593 | ), | 627 | ), |
594 | full_range: 15..77, | 628 | full_range: 22..323, |
595 | focus_range: Some( | 629 | focus_range: Some( |
596 | 19..27, | 630 | 26..40, |
597 | ), | 631 | ), |
598 | name: "test_mod", | 632 | name: "nested_tests_0", |
599 | kind: MODULE, | 633 | kind: MODULE, |
600 | container_name: None, | 634 | container_name: None, |
601 | description: None, | 635 | description: None, |
602 | docs: None, | 636 | docs: None, |
603 | }, | 637 | }, |
604 | kind: TestMod { | 638 | kind: TestMod { |
605 | path: "foo::test_mod", | 639 | path: "root_tests::nested_tests_0", |
606 | }, | 640 | }, |
607 | cfg_exprs: [], | 641 | cfg_exprs: [], |
608 | }, | 642 | }, |
@@ -611,11 +645,31 @@ mod foo { | |||
611 | file_id: FileId( | 645 | file_id: FileId( |
612 | 1, | 646 | 1, |
613 | ), | 647 | ), |
614 | full_range: 38..71, | 648 | full_range: 51..192, |
615 | focus_range: Some( | 649 | focus_range: Some( |
616 | 57..66, | 650 | 55..69, |
617 | ), | 651 | ), |
618 | name: "test_foo1", | 652 | name: "nested_tests_1", |
653 | kind: MODULE, | ||
654 | container_name: None, | ||
655 | description: None, | ||
656 | docs: None, | ||
657 | }, | ||
658 | kind: TestMod { | ||
659 | path: "root_tests::nested_tests_0::nested_tests_1", | ||
660 | }, | ||
661 | cfg_exprs: [], | ||
662 | }, | ||
663 | Runnable { | ||
664 | nav: NavigationTarget { | ||
665 | file_id: FileId( | ||
666 | 1, | ||
667 | ), | ||
668 | full_range: 84..126, | ||
669 | focus_range: Some( | ||
670 | 107..121, | ||
671 | ), | ||
672 | name: "nested_test_11", | ||
619 | kind: FN_DEF, | 673 | kind: FN_DEF, |
620 | container_name: None, | 674 | container_name: None, |
621 | description: None, | 675 | description: None, |
@@ -623,7 +677,7 @@ mod foo { | |||
623 | }, | 677 | }, |
624 | kind: Test { | 678 | kind: Test { |
625 | test_id: Path( | 679 | test_id: Path( |
626 | "foo::test_mod::test_foo1", | 680 | "root_tests::nested_tests_0::nested_tests_1::nested_test_11", |
627 | ), | 681 | ), |
628 | attr: TestAttr { | 682 | attr: TestAttr { |
629 | ignore: false, | 683 | ignore: false, |
@@ -631,46 +685,48 @@ mod foo { | |||
631 | }, | 685 | }, |
632 | cfg_exprs: [], | 686 | cfg_exprs: [], |
633 | }, | 687 | }, |
634 | ] | ||
635 | "#]], | ||
636 | ); | ||
637 | } | ||
638 | |||
639 | #[test] | ||
640 | fn test_runnables_multiple_depth_module() { | ||
641 | check( | ||
642 | r#" | ||
643 | //- /lib.rs | ||
644 | <|> | ||
645 | mod foo { | ||
646 | mod bar { | ||
647 | mod test_mod { | ||
648 | #[test] | ||
649 | fn test_foo1() {} | ||
650 | } | ||
651 | } | ||
652 | } | ||
653 | "#, | ||
654 | &[&TEST, &TEST], | ||
655 | expect![[r#" | ||
656 | [ | ||
657 | Runnable { | 688 | Runnable { |
658 | nav: NavigationTarget { | 689 | nav: NavigationTarget { |
659 | file_id: FileId( | 690 | file_id: FileId( |
660 | 1, | 691 | 1, |
661 | ), | 692 | ), |
662 | full_range: 33..107, | 693 | full_range: 140..182, |
663 | focus_range: Some( | 694 | focus_range: Some( |
664 | 37..45, | 695 | 163..177, |
665 | ), | 696 | ), |
666 | name: "test_mod", | 697 | name: "nested_test_12", |
698 | kind: FN_DEF, | ||
699 | container_name: None, | ||
700 | description: None, | ||
701 | docs: None, | ||
702 | }, | ||
703 | kind: Test { | ||
704 | test_id: Path( | ||
705 | "root_tests::nested_tests_0::nested_tests_1::nested_test_12", | ||
706 | ), | ||
707 | attr: TestAttr { | ||
708 | ignore: false, | ||
709 | }, | ||
710 | }, | ||
711 | cfg_exprs: [], | ||
712 | }, | ||
713 | Runnable { | ||
714 | nav: NavigationTarget { | ||
715 | file_id: FileId( | ||
716 | 1, | ||
717 | ), | ||
718 | full_range: 202..286, | ||
719 | focus_range: Some( | ||
720 | 206..220, | ||
721 | ), | ||
722 | name: "nested_tests_2", | ||
667 | kind: MODULE, | 723 | kind: MODULE, |
668 | container_name: None, | 724 | container_name: None, |
669 | description: None, | 725 | description: None, |
670 | docs: None, | 726 | docs: None, |
671 | }, | 727 | }, |
672 | kind: TestMod { | 728 | kind: TestMod { |
673 | path: "foo::bar::test_mod", | 729 | path: "root_tests::nested_tests_0::nested_tests_2", |
674 | }, | 730 | }, |
675 | cfg_exprs: [], | 731 | cfg_exprs: [], |
676 | }, | 732 | }, |
@@ -679,11 +735,11 @@ mod foo { | |||
679 | file_id: FileId( | 735 | file_id: FileId( |
680 | 1, | 736 | 1, |
681 | ), | 737 | ), |
682 | full_range: 60..97, | 738 | full_range: 235..276, |
683 | focus_range: Some( | 739 | focus_range: Some( |
684 | 83..92, | 740 | 258..271, |
685 | ), | 741 | ), |
686 | name: "test_foo1", | 742 | name: "nested_test_2", |
687 | kind: FN_DEF, | 743 | kind: FN_DEF, |
688 | container_name: None, | 744 | container_name: None, |
689 | description: None, | 745 | description: None, |
@@ -691,7 +747,7 @@ mod foo { | |||
691 | }, | 747 | }, |
692 | kind: Test { | 748 | kind: Test { |
693 | test_id: Path( | 749 | test_id: Path( |
694 | "foo::bar::test_mod::test_foo1", | 750 | "root_tests::nested_tests_0::nested_tests_2::nested_test_2", |
695 | ), | 751 | ), |
696 | attr: TestAttr { | 752 | attr: TestAttr { |
697 | ignore: false, | 753 | ignore: false, |