@@ -216,6 +216,7 @@ class TestItem:
216216 range : Optional [Range ] = None
217217 tags : Optional [List [str ]] = None
218218 error : Optional [str ] = None
219+ rpa : Optional [bool ] = None
219220
220221
221222@dataclass
@@ -228,7 +229,9 @@ class ResultItem:
228229class Statistics :
229230 suites : int = 0
230231 suites_with_tests : int = 0
232+ suites_with_tasks : int = 0
231233 tests : int = 0
234+ tasks : int = 0
232235
233236
234237def get_rel_source (source : Optional [str ]) -> Optional [str ]:
@@ -254,7 +257,7 @@ def __init__(self) -> None:
254257 )
255258 self ._current = self .all
256259 self .suites : List [TestItem ] = []
257- self .tests : List [TestItem ] = []
260+ self .test_and_tasks : List [TestItem ] = []
258261 self .tags : Dict [str , List [TestItem ]] = defaultdict (list )
259262 self .normalized_tags : Dict [str , List [TestItem ]] = defaultdict (list )
260263 self .statistics = Statistics ()
@@ -294,6 +297,7 @@ def visit_suite(self, suite: TestSuite) -> None:
294297 ),
295298 children = [],
296299 error = suite .error_message if isinstance (suite , ErroneousTestSuite ) else None ,
300+ rpa = suite .rpa ,
297301 )
298302 except ValueError as e :
299303 raise ValueError (f"Error while parsing suite { suite .source } : { e } " ) from e
@@ -313,7 +317,10 @@ def visit_suite(self, suite: TestSuite) -> None:
313317
314318 self .statistics .suites += 1
315319 if suite .tests :
316- self .statistics .suites_with_tests += 1
320+ if suite .rpa :
321+ self .statistics .suites_with_tasks += 1
322+ else :
323+ self .statistics .suites_with_tests += 1
317324
318325 def end_suite (self , _suite : TestSuite ) -> None :
319326 self ._collected .pop ()
@@ -332,7 +339,7 @@ def visit_test(self, test: TestCase) -> None:
332339 try :
333340 absolute_path = normalized_path (Path (test .source )) if test .source is not None else None
334341 item = TestItem (
335- type = "test" ,
342+ type = "task" if self . _current . rpa else " test" ,
336343 id = f"{ absolute_path or '' } ;{ test .longname } ;{ test .lineno } " ,
337344 name = test .name ,
338345 longname = test .longname ,
@@ -344,6 +351,7 @@ def visit_test(self, test: TestCase) -> None:
344351 end = Position (line = test .lineno - 1 , character = 0 ),
345352 ),
346353 tags = list (set (normalize (str (t ), ignore = "_" ) for t in test .tags )) if test .tags else None ,
354+ rpa = self ._current .rpa ,
347355 )
348356 except ValueError as e :
349357 raise ValueError (f"Error while parsing suite { test .source } : { e } " ) from e
@@ -352,10 +360,12 @@ def visit_test(self, test: TestCase) -> None:
352360 self .tags [str (tag )].append (item )
353361 self .normalized_tags [normalize (str (tag ), ignore = "_" )].append (item )
354362
355- self .tests .append (item )
363+ self .test_and_tasks .append (item )
356364 self ._current .children .append (item )
357-
358- self .statistics .tests += 1
365+ if self ._current .rpa :
366+ self .statistics .tasks += 1
367+ else :
368+ self .statistics .tests += 1
359369
360370
361371@click .group (invoke_without_command = False )
@@ -543,6 +553,28 @@ def handle_options(
543553 raise UnknownError ("Unexpected error happened." )
544554
545555
556+ def print_statistics (app : Application , suite : TestSuite , collector : Collector ) -> None :
557+ def print () -> Iterable [str ]:
558+ yield click .style ("Statistics:" , underline = True , fg = "blue" )
559+ yield os .linesep
560+ yield click .style (" - Suites: " , underline = True , bold = True , fg = "blue" )
561+ yield f"{ collector .statistics .suites } { os .linesep } "
562+ if collector .statistics .suites_with_tests :
563+ yield click .style (" - Suites with tests: " , underline = True , bold = True , fg = "blue" )
564+ yield f"{ collector .statistics .suites_with_tests } { os .linesep } "
565+ if collector .statistics .suites_with_tasks :
566+ yield click .style (" - Suites with tasks: " , underline = True , bold = True , fg = "blue" )
567+ yield f"{ collector .statistics .suites_with_tasks } { os .linesep } "
568+ if collector .statistics .tests :
569+ yield click .style (" - Tests: " , underline = True , bold = True , fg = "blue" )
570+ yield f"{ collector .statistics .tests } { os .linesep } "
571+ if collector .statistics .tasks :
572+ yield click .style (" - Tasks: " , underline = True , bold = True , fg = "blue" )
573+ yield f"{ collector .statistics .tasks } { os .linesep } "
574+
575+ app .echo_via_pager (print ())
576+
577+
546578@discover .command (
547579 context_settings = {"allow_extra_args" : True , "ignore_unknown_options" : True },
548580 add_help_option = True ,
@@ -551,7 +583,7 @@ def handle_options(
551583@click .option (
552584 "--tags / --no-tags" ,
553585 "show_tags" ,
554- default = False ,
586+ default = True ,
555587 show_default = True ,
556588 help = "Show the tags that are present." ,
557589)
@@ -591,48 +623,70 @@ def all(
591623
592624 if collector .all .children :
593625 if app .config .output_format is None or app .config .output_format == OutputFormat .TEXT :
594- tests_or_tasks = "Task" if suite .rpa else "Test"
595626
596627 def print (item : TestItem , indent : int = 0 ) -> Iterable [str ]:
597- type = click .style (
598- item .type .capitalize () if item .type == "suite" else tests_or_tasks .capitalize (),
599- fg = "green" ,
600- )
601-
602- if item .type == "test" :
628+ if item .type in ["test" , "task" ]:
603629 yield " "
604- yield type
605- yield click .style (f": { item .longname } " , bold = True )
630+ yield click . style ( f" { item . type . capitalize () } : " , fg = "blue" )
631+ yield click .style (item .longname , bold = True )
606632 yield click .style (
607633 f" ({ item .source if full_paths else item .rel_source } "
608634 f":{ item .range .start .line + 1 if item .range is not None else 1 } ){ os .linesep } "
609635 )
610636 if show_tags and item .tags :
611- yield click .style (" Tags:" , bold = True , fg = "green " )
637+ yield click .style (" Tags:" , bold = True , fg = "yellow " )
612638 yield f" { ', ' . join (normalize (str (tag ), ignore = '_' ) for tag in sorted (item .tags ))} { os .linesep } "
613639 else :
614- yield type
615- yield f": { item .longname } "
640+ yield click . style ( f" { item . type . capitalize () } : " , fg = "green" )
641+ yield click . style ( item .longname , bold = True )
616642 yield click .style (f" ({ item .source if full_paths else item .rel_source } ){ os .linesep } " )
617643 for child in item .children or []:
618644 yield from print (child , indent + 2 )
619645
620- if indent == 0 :
621- yield os .linesep
622-
623- yield click .style ("Suites: " , underline = True , bold = True , fg = "blue" )
624- yield f"{ collector .statistics .suites } { os .linesep } "
625- yield click .style (f"Suites with { tests_or_tasks } : " , underline = True , bold = True , fg = "blue" )
626- yield f"{ collector .statistics .suites_with_tests } { os .linesep } "
627- yield click .style (f"{ tests_or_tasks } : " , underline = True , bold = True , fg = "blue" )
628- yield f"{ collector .statistics .tests } { os .linesep } "
629-
630646 app .echo_via_pager (print (collector .all .children [0 ]))
647+ print_statistics (app , suite , collector )
631648
632649 else :
633650 app .print_data (ResultItem ([collector .all ], diagnostics ), remove_defaults = True )
634651
635652
653+ def _test_or_tasks (
654+ selected_type : str ,
655+ app : Application ,
656+ full_paths : bool ,
657+ show_tags : bool ,
658+ by_longname : Tuple [str , ...],
659+ exclude_by_longname : Tuple [str , ...],
660+ robot_options_and_args : Tuple [str , ...],
661+ ) -> None :
662+ suite , collector , diagnostics = handle_options (app , by_longname , exclude_by_longname , robot_options_and_args )
663+
664+ if collector .all .children :
665+ if app .config .output_format is None or app .config .output_format == OutputFormat .TEXT :
666+
667+ def print (items : List [TestItem ]) -> Iterable [str ]:
668+ for item in items :
669+ if item .type != selected_type :
670+ continue
671+
672+ yield click .style (f"{ item .type .capitalize ()} : " , fg = "blue" )
673+ yield click .style (item .longname , bold = True )
674+ yield click .style (
675+ f" ({ item .source if full_paths else item .rel_source } "
676+ f":{ item .range .start .line + 1 if item .range is not None else 1 } ){ os .linesep } "
677+ )
678+ if show_tags and item .tags :
679+ yield click .style (" Tags:" , bold = True , fg = "yellow" )
680+ yield f" { ', ' . join (normalize (str (tag ), ignore = '_' ) for tag in sorted (item .tags ))} { os .linesep } "
681+
682+ if collector .test_and_tasks :
683+ app .echo_via_pager (print (collector .test_and_tasks ))
684+ print_statistics (app , suite , collector )
685+
686+ else :
687+ app .print_data (ResultItem (collector .test_and_tasks , diagnostics ), remove_defaults = True )
688+
689+
636690@discover .command (
637691 context_settings = {"allow_extra_args" : True , "ignore_unknown_options" : True },
638692 add_help_option = True ,
@@ -677,34 +731,53 @@ def tests(
677731 ```
678732 """
679733
680- suite , collector , diagnostics = handle_options (app , by_longname , exclude_by_longname , robot_options_and_args )
681-
682- if collector .all .children :
683- if app .config .output_format is None or app .config .output_format == OutputFormat .TEXT :
734+ _test_or_tasks ("test" , app , full_paths , show_tags , by_longname , exclude_by_longname , robot_options_and_args )
684735
685- tests_or_tasks = "Task" if suite .rpa else "Test"
686736
687- def print (items : List [TestItem ]) -> Iterable [str ]:
688- for item in items :
689- type = click .style (
690- item .type .capitalize () if item .type == "suite" else tests_or_tasks .capitalize (),
691- fg = "blue" ,
692- )
693- yield type
694- yield click .style (f": { item .longname } " , bold = True )
695- yield click .style (
696- f" ({ item .source if full_paths else item .rel_source } "
697- f":{ item .range .start .line + 1 if item .range is not None else 1 } ){ os .linesep } "
698- )
699- if show_tags and item .tags :
700- yield click .style (" Tags:" , bold = True , fg = "green" )
701- yield f" { ', ' . join (normalize (str (tag ), ignore = '_' ) for tag in sorted (item .tags ))} { os .linesep } "
737+ @discover .command (
738+ context_settings = {"allow_extra_args" : True , "ignore_unknown_options" : True },
739+ add_help_option = True ,
740+ epilog = "Use `-- --help` to see `robot` help." ,
741+ )
742+ @click .option (
743+ "--tags / --no-tags" ,
744+ "show_tags" ,
745+ default = False ,
746+ show_default = True ,
747+ help = "Show the tags that are present." ,
748+ )
749+ @click .option (
750+ "--full-paths / --no-full-paths" ,
751+ "full_paths" ,
752+ default = False ,
753+ show_default = True ,
754+ help = "Show full paths instead of releative." ,
755+ )
756+ @add_options (* ROBOT_OPTIONS )
757+ @pass_application
758+ def tasks (
759+ app : Application ,
760+ full_paths : bool ,
761+ show_tags : bool ,
762+ by_longname : Tuple [str , ...],
763+ exclude_by_longname : Tuple [str , ...],
764+ robot_options_and_args : Tuple [str , ...],
765+ ) -> None :
766+ """\
767+ Discover tasks with the selected configuration, profiles, options and
768+ arguments.
702769
703- if collector .tests :
704- app .echo_via_pager (print (collector .tests ))
770+ You can use all known `robot` arguments to filter for example by tags or to use pre-run-modifier.
705771
706- else :
707- app .print_data (ResultItem (collector .tests , diagnostics ), remove_defaults = True )
772+ \b
773+ Examples:
774+ ```
775+ robotcode discover tasks
776+ robotcode --profile regression discover tasks
777+ robotcode --profile regression discover tasks --include regression --exclude wipANDnotready
778+ ```
779+ """
780+ _test_or_tasks ("task" , app , full_paths , show_tags , by_longname , exclude_by_longname , robot_options_and_args )
708781
709782
710783@discover .command (
@@ -743,7 +816,7 @@ def suites(
743816 ```
744817 """
745818
746- _suite , collector , diagnostics = handle_options (app , by_longname , exclude_by_longname , robot_options_and_args )
819+ suite , collector , diagnostics = handle_options (app , by_longname , exclude_by_longname , robot_options_and_args )
747820
748821 if collector .all .children :
749822 if app .config .output_format is None or app .config .output_format == OutputFormat .TEXT :
@@ -760,6 +833,8 @@ def print(items: List[TestItem]) -> Iterable[str]:
760833 if collector .suites :
761834 app .echo_via_pager (print (collector .suites ))
762835
836+ print_statistics (app , suite , collector )
837+
763838 else :
764839 app .print_data (ResultItem (collector .suites , diagnostics ), remove_defaults = True )
765840
@@ -788,6 +863,13 @@ class TagsResult:
788863 show_default = True ,
789864 help = "Show tests where the tag is present." ,
790865)
866+ @click .option (
867+ "--tasks / --no-tasks" ,
868+ "show_tasks" ,
869+ default = False ,
870+ show_default = True ,
871+ help = "Show tasks where the tag is present." ,
872+ )
791873@click .option (
792874 "--full-paths / --no-full-paths" ,
793875 "full_paths" ,
@@ -801,6 +883,7 @@ def tags(
801883 app : Application ,
802884 normalized : bool ,
803885 show_tests : bool ,
886+ show_tasks : bool ,
804887 full_paths : bool ,
805888 by_longname : Tuple [str , ...],
806889 exclude_by_longname : Tuple [str , ...],
@@ -822,7 +905,7 @@ def tags(
822905 ```
823906 """
824907
825- _suite , collector , _diagnostics = handle_options (app , by_longname , exclude_by_longname , robot_options_and_args )
908+ suite , collector , _diagnostics = handle_options (app , by_longname , exclude_by_longname , robot_options_and_args )
826909
827910 if collector .all .children :
828911 if app .config .output_format is None or app .config .output_format == OutputFormat .TEXT :
@@ -832,18 +915,26 @@ def print(tags: Dict[str, List[TestItem]]) -> Iterable[str]:
832915 yield click .style (
833916 f"{ tag } { os .linesep } " ,
834917 bold = show_tests ,
835- fg = "green " if show_tests else None ,
918+ fg = "yellow " if show_tests else None ,
836919 )
837- if show_tests :
920+ if show_tests or show_tasks :
838921 for t in items :
839- yield click .style (f" { t .longname } " , bold = True ) + click .style (
922+ if show_tests != show_tasks :
923+ if show_tests and t .type != "test" :
924+ continue
925+ if show_tasks and t .type != "task" :
926+ continue
927+ yield click .style (f" { t .type .capitalize ()} : " , fg = "blue" )
928+ yield click .style (t .longname , bold = True ) + click .style (
840929 f" ({ t .source if full_paths else t .rel_source } "
841930 f":{ t .range .start .line + 1 if t .range is not None else 1 } ){ os .linesep } "
842931 )
843932
844933 if collector .normalized_tags :
845934 app .echo_via_pager (print (collector .normalized_tags if normalized else collector .tags ))
846935
936+ print_statistics (app , suite , collector )
937+
847938 else :
848939 app .print_data (TagsResult (collector .normalized_tags ), remove_defaults = True )
849940
0 commit comments