From b8546ac5f1047bb4b90c792a7e05b7f7d29cb2bd Mon Sep 17 00:00:00 2001 From: jce Date: Wed, 12 Jul 2023 11:41:01 +0200 Subject: [PATCH 01/12] Add option to filter test cases by tags --- mlx/robot2rst.py | 5 ++++- mlx/robot_parser.py | 14 ++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/mlx/robot2rst.py b/mlx/robot2rst.py index 57bfa6b..4d7ec3f 100644 --- a/mlx/robot2rst.py +++ b/mlx/robot2rst.py @@ -97,6 +97,9 @@ def main(): parser.add_argument("-t", "--tags", nargs='*', help="Regex(es) for matching tags to add a relationship link for. All tags get matched by " "default.") + parser.add_argument("--tags-for-inclusion", nargs='*', default=[], + help="Regex(es) for matching tags. Only test cases that have at least one matching tag are " + "included. All are included by default.") parser.add_argument("-c", "--coverage", nargs='*', help="Minumum coverage percentages for the item-matrix(es); 1 value per tag in -t, --tags.") parser.add_argument("--type", default='q', @@ -137,7 +140,7 @@ def main(): f"percentages ({len(coverages)}).") relationship_config = [(relationships[i], tag_regexes[i], coverages[i]) for i in range(len(relationships))] - parser = ParserApplication(Path(args.robot_file)) + parser = ParserApplication(Path(args.robot_file), args.tags_for_inclusion) parser.run() return generate_robot_2_rst(parser, Path(args.rst_file), prefix, relationship_config, gen_matrix, test_type=test_type, only=args.expression, coverages=coverages) diff --git a/mlx/robot_parser.py b/mlx/robot_parser.py index 2dc061a..dde98ed 100644 --- a/mlx/robot_parser.py +++ b/mlx/robot_parser.py @@ -16,17 +16,19 @@ class ParserApplication(ModelVisitor): """ TestAttributes = namedtuple('TestAttributes', 'name doc tags') - def __init__(self, robot_file, *args, **kwargs): + def __init__(self, robot_file, tags_for_inclusion, *args, **kwargs): """ Constructor Args: robot_file (Path): Path to the .robot file. + include_tags (list): Regexes for matching tags to only include test cases that have at least one matching tag. """ super().__init__(*args, **kwargs) self.robot_file = str(robot_file.resolve(strict=True)) self.model = get_model(self.robot_file) self.tests = [] self.variables = {} + self.tags_for_inclusion = tags_for_inclusion def run(self): self.visit(self.model) @@ -63,5 +65,13 @@ def visit_TestCase(self, node): previous_token = token elif element_type == Token.TAGS: tags = [el.value for el in element.tokens if el.type == Token.ARGUMENT] + if self.evaluate_inclusion(tags): + self.tests.append(self.TestAttributes(node.name, doc, tags)) - self.tests.append(self.TestAttributes(node.name, doc, tags)) + def evaluate_inclusion(self, tags): + for pattern in self.tags_for_inclusion: + regexp = re.compile(pattern) + for tag in tags: + if regexp.search(tag): + return True + return not bool(self.tags_for_inclusion) From df55572deceef8dce9208e4bfcb2a7313ae485e1 Mon Sep 17 00:00:00 2001 From: jce Date: Wed, 12 Jul 2023 12:03:35 +0200 Subject: [PATCH 02/12] Update usage --- README.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 44d84f5..a3037ef 100644 --- a/README.rst +++ b/README.rst @@ -40,7 +40,8 @@ Usage $ robot2rst --help usage: robot2rst [-h] -i ROBOT_FILE -o RST_FILE [--only EXPRESSION] [-p PREFIX] - [-r [RELATIONSHIPS [RELATIONSHIPS ...]]] [-t [TAGS [TAGS ...]]] + [-r [RELATIONSHIPS ...]] [-t [TAGS ...]] + [--tags-for-inclusion [TAGS_FOR_INCLUSION ...]] [-c [COVERAGE ...]] [--type TYPE] [--trim-suffix] Convert robot test cases to reStructuredText with traceable items. @@ -61,6 +62,9 @@ Usage -t [TAGS ...], --tags [TAGS ...] Regex(es) for matching tags to add a relationship link for. All tags get matched by default. + --tags-for-inclusion [TAGS_FOR_INCLUSION ...] + Regex(es) for matching tags. Only test cases that have at least one + matching tag are included. All are included by default. -c [COVERAGE ...], --coverage [COVERAGE ...] Minumum coverage percentages for the item-matrix(es); 1 value per tag in -t, --tags. From 9c8dd50f6b7b0c9c9869f6b5f8fb0fb29e7ce187 Mon Sep 17 00:00:00 2001 From: jce Date: Wed, 12 Jul 2023 12:38:03 +0200 Subject: [PATCH 03/12] Fix line length --- mlx/robot_parser.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mlx/robot_parser.py b/mlx/robot_parser.py index dde98ed..fa13db9 100644 --- a/mlx/robot_parser.py +++ b/mlx/robot_parser.py @@ -21,7 +21,8 @@ def __init__(self, robot_file, tags_for_inclusion, *args, **kwargs): Args: robot_file (Path): Path to the .robot file. - include_tags (list): Regexes for matching tags to only include test cases that have at least one matching tag. + include_tags (list): Regexes for matching tags to only include test cases that have at least one matching + tag. """ super().__init__(*args, **kwargs) self.robot_file = str(robot_file.resolve(strict=True)) From 2f4be6569f1328353e74722b4fe8c46e6a93c3f9 Mon Sep 17 00:00:00 2001 From: jce Date: Wed, 12 Jul 2023 14:22:23 +0200 Subject: [PATCH 04/12] All regexes must match at least one tag for a test case to be included --- README.rst | 4 ++-- mlx/robot2rst.py | 4 ++-- mlx/robot_parser.py | 12 +++++++----- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/README.rst b/README.rst index a3037ef..5bbadd2 100644 --- a/README.rst +++ b/README.rst @@ -63,8 +63,8 @@ Usage Regex(es) for matching tags to add a relationship link for. All tags get matched by default. --tags-for-inclusion [TAGS_FOR_INCLUSION ...] - Regex(es) for matching tags. Only test cases that have at least one - matching tag are included. All are included by default. + Regex(es) for matching tags. A test case is included if every regex + matches at least one of its tags. -c [COVERAGE ...], --coverage [COVERAGE ...] Minumum coverage percentages for the item-matrix(es); 1 value per tag in -t, --tags. diff --git a/mlx/robot2rst.py b/mlx/robot2rst.py index 4d7ec3f..c563c3c 100644 --- a/mlx/robot2rst.py +++ b/mlx/robot2rst.py @@ -98,8 +98,8 @@ def main(): help="Regex(es) for matching tags to add a relationship link for. All tags get matched by " "default.") parser.add_argument("--tags-for-inclusion", nargs='*', default=[], - help="Regex(es) for matching tags. Only test cases that have at least one matching tag are " - "included. All are included by default.") + help="Regex(es) for matching tags. A test case is included if every regex matches at least " + "one of its tags.") parser.add_argument("-c", "--coverage", nargs='*', help="Minumum coverage percentages for the item-matrix(es); 1 value per tag in -t, --tags.") parser.add_argument("--type", default='q', diff --git a/mlx/robot_parser.py b/mlx/robot_parser.py index fa13db9..42029db 100644 --- a/mlx/robot_parser.py +++ b/mlx/robot_parser.py @@ -21,8 +21,8 @@ def __init__(self, robot_file, tags_for_inclusion, *args, **kwargs): Args: robot_file (Path): Path to the .robot file. - include_tags (list): Regexes for matching tags to only include test cases that have at least one matching - tag. + include_tags (list): Regexes for matching tags. A test case is included if every regex matches at least + one of its tags. """ super().__init__(*args, **kwargs) self.robot_file = str(robot_file.resolve(strict=True)) @@ -73,6 +73,8 @@ def evaluate_inclusion(self, tags): for pattern in self.tags_for_inclusion: regexp = re.compile(pattern) for tag in tags: - if regexp.search(tag): - return True - return not bool(self.tags_for_inclusion) + if regexp.match(tag): + break + else: + return False + return True From 9f56fb93c172fecedeb89d0c88851d533aa35104 Mon Sep 17 00:00:00 2001 From: Jasper Craeghs Date: Tue, 25 Jul 2023 11:39:15 +0200 Subject: [PATCH 05/12] Fix typo --- mlx/robot2rst.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mlx/robot2rst.py b/mlx/robot2rst.py index c563c3c..66e3195 100644 --- a/mlx/robot2rst.py +++ b/mlx/robot2rst.py @@ -101,7 +101,7 @@ def main(): help="Regex(es) for matching tags. A test case is included if every regex matches at least " "one of its tags.") parser.add_argument("-c", "--coverage", nargs='*', - help="Minumum coverage percentages for the item-matrix(es); 1 value per tag in -t, --tags.") + help="Minimum coverage percentages for the item-matrix(es); 1 value per tag in -t, --tags.") parser.add_argument("--type", default='q', help="Give value that starts with 'q' or 'i' (case-insensitive) to explicitly define " "the type of test: qualification/integration test. The default is 'qualification'.") From 0b2c0d04e4570a781e24ba2814e18aae9f34af1b Mon Sep 17 00:00:00 2001 From: Jasper Craeghs Date: Tue, 25 Jul 2023 12:55:16 +0200 Subject: [PATCH 06/12] Enhance documentation --- README.rst | 8 ++++---- mlx/robot2rst.py | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/README.rst b/README.rst index 5bbadd2..72c4cc1 100644 --- a/README.rst +++ b/README.rst @@ -60,11 +60,11 @@ Usage Name(s) of the relationship(s) used to link to items in Tags section. The default value is 'validates'. -t [TAGS ...], --tags [TAGS ...] - Regex(es) for matching tags to add a relationship link for. All tags - get matched by default. + Regex(es) for matching tags to treat them as traceable targets via a + relationship. All tags get matched by default. --tags-for-inclusion [TAGS_FOR_INCLUSION ...] - Regex(es) for matching tags. A test case is included if every regex - matches at least one of its tags. + Regex(es) for matching tags to filter test cases. A test case is + included if every regex matches at least one of its tags. -c [COVERAGE ...], --coverage [COVERAGE ...] Minumum coverage percentages for the item-matrix(es); 1 value per tag in -t, --tags. diff --git a/mlx/robot2rst.py b/mlx/robot2rst.py index 66e3195..4a0ddda 100644 --- a/mlx/robot2rst.py +++ b/mlx/robot2rst.py @@ -95,11 +95,11 @@ def main(): help="Name(s) of the relationship(s) used to link to items in Tags section. The default value " "is 'validates'.") parser.add_argument("-t", "--tags", nargs='*', - help="Regex(es) for matching tags to add a relationship link for. All tags get matched by " - "default.") + help="Regex(es) for matching tags to treat them as traceable targets via a relationship. " + "All tags get matched by default.") parser.add_argument("--tags-for-inclusion", nargs='*', default=[], - help="Regex(es) for matching tags. A test case is included if every regex matches at least " - "one of its tags.") + help="Regex(es) for matching tags to filter test cases. A test case is included if every " + "regex matches at least one of its tags.") parser.add_argument("-c", "--coverage", nargs='*', help="Minimum coverage percentages for the item-matrix(es); 1 value per tag in -t, --tags.") parser.add_argument("--type", default='q', From 8c93a902745524d0c9b828866003ce87495b155d Mon Sep 17 00:00:00 2001 From: Jasper Craeghs Date: Tue, 25 Jul 2023 12:55:30 +0200 Subject: [PATCH 07/12] Fix typo --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 72c4cc1..d18ef6b 100644 --- a/README.rst +++ b/README.rst @@ -66,7 +66,7 @@ Usage Regex(es) for matching tags to filter test cases. A test case is included if every regex matches at least one of its tags. -c [COVERAGE ...], --coverage [COVERAGE ...] - Minumum coverage percentages for the item-matrix(es); 1 value per tag + Minimum coverage percentages for the item-matrix(es); 1 value per tag in -t, --tags. --type TYPE Give value that starts with 'q' or 'i' (case-insensitive) to explicitly define the type of test: qualification/integration test. From 63529ba7e28d83bb7c602e37fa7ba0ccd4ad82dd Mon Sep 17 00:00:00 2001 From: jce Date: Thu, 24 Aug 2023 10:43:15 +0200 Subject: [PATCH 08/12] Align option name with RF --- README.rst | 11 +++++------ mlx/robot2rst.py | 4 ++-- mlx/robot_parser.py | 4 ++-- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/README.rst b/README.rst index d18ef6b..345321e 100644 --- a/README.rst +++ b/README.rst @@ -40,9 +40,8 @@ Usage $ robot2rst --help usage: robot2rst [-h] -i ROBOT_FILE -o RST_FILE [--only EXPRESSION] [-p PREFIX] - [-r [RELATIONSHIPS ...]] [-t [TAGS ...]] - [--tags-for-inclusion [TAGS_FOR_INCLUSION ...]] [-c [COVERAGE ...]] - [--type TYPE] [--trim-suffix] + [-r [RELATIONSHIPS ...]] [-t [TAGS ...]] [--include [INCLUDE ...]] + [-c [COVERAGE ...]] [--type TYPE] [--trim-suffix] Convert robot test cases to reStructuredText with traceable items. @@ -52,8 +51,8 @@ Usage Input robot file -o RST_FILE, --rst RST_FILE Output RST file, e.g. my_component_qtp.rst - --only EXPRESSION Expression of tags for Sphinx' `only` directive that surrounds all RST - content. By default, no `only` directive is generated. + --only EXPRESSION Expression of tags for Sphinx' `only` directive that surrounds all + RST content. By default, no `only` directive is generated. -p PREFIX, --prefix PREFIX Overrides the default 'QTEST-' prefix. -r [RELATIONSHIPS ...], --relationships [RELATIONSHIPS ...] @@ -62,7 +61,7 @@ Usage -t [TAGS ...], --tags [TAGS ...] Regex(es) for matching tags to treat them as traceable targets via a relationship. All tags get matched by default. - --tags-for-inclusion [TAGS_FOR_INCLUSION ...] + --include [INCLUDE ...] Regex(es) for matching tags to filter test cases. A test case is included if every regex matches at least one of its tags. -c [COVERAGE ...], --coverage [COVERAGE ...] diff --git a/mlx/robot2rst.py b/mlx/robot2rst.py index 4a0ddda..075b709 100644 --- a/mlx/robot2rst.py +++ b/mlx/robot2rst.py @@ -97,7 +97,7 @@ def main(): parser.add_argument("-t", "--tags", nargs='*', help="Regex(es) for matching tags to treat them as traceable targets via a relationship. " "All tags get matched by default.") - parser.add_argument("--tags-for-inclusion", nargs='*', default=[], + parser.add_argument("--include", nargs='*', default=[], help="Regex(es) for matching tags to filter test cases. A test case is included if every " "regex matches at least one of its tags.") parser.add_argument("-c", "--coverage", nargs='*', @@ -140,7 +140,7 @@ def main(): f"percentages ({len(coverages)}).") relationship_config = [(relationships[i], tag_regexes[i], coverages[i]) for i in range(len(relationships))] - parser = ParserApplication(Path(args.robot_file), args.tags_for_inclusion) + parser = ParserApplication(Path(args.robot_file), args.include) parser.run() return generate_robot_2_rst(parser, Path(args.rst_file), prefix, relationship_config, gen_matrix, test_type=test_type, only=args.expression, coverages=coverages) diff --git a/mlx/robot_parser.py b/mlx/robot_parser.py index 42029db..5d49040 100644 --- a/mlx/robot_parser.py +++ b/mlx/robot_parser.py @@ -21,8 +21,8 @@ def __init__(self, robot_file, tags_for_inclusion, *args, **kwargs): Args: robot_file (Path): Path to the .robot file. - include_tags (list): Regexes for matching tags. A test case is included if every regex matches at least - one of its tags. + tags_for_inclusion (list): Regexes for matching tags. A test case is included if every regex matches at + least one of its tags. """ super().__init__(*args, **kwargs) self.robot_file = str(robot_file.resolve(strict=True)) From a4e6e4bcb58b897b546aa73047d71011ad5ac76c Mon Sep 17 00:00:00 2001 From: jce Date: Thu, 31 Aug 2023 14:59:58 +0200 Subject: [PATCH 09/12] Specify that regexes shall be in the Python syntax --- mlx/robot2rst.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mlx/robot2rst.py b/mlx/robot2rst.py index 075b709..49598b3 100644 --- a/mlx/robot2rst.py +++ b/mlx/robot2rst.py @@ -95,11 +95,11 @@ def main(): help="Name(s) of the relationship(s) used to link to items in Tags section. The default value " "is 'validates'.") parser.add_argument("-t", "--tags", nargs='*', - help="Regex(es) for matching tags to treat them as traceable targets via a relationship. " - "All tags get matched by default.") + help="Zero or more Python regexes for matching tags to treat them as traceable targets via a " + "relationship. All tags get matched by default.") parser.add_argument("--include", nargs='*', default=[], - help="Regex(es) for matching tags to filter test cases. A test case is included if every " - "regex matches at least one of its tags.") + help="Zero or more Python regexes for matching tags to filter test cases. A test case is " + "included if every regex matches at least one of its tags.") parser.add_argument("-c", "--coverage", nargs='*', help="Minimum coverage percentages for the item-matrix(es); 1 value per tag in -t, --tags.") parser.add_argument("--type", default='q', From 962e4ce9b5b9b8143af09fa6980507b1e5921bf1 Mon Sep 17 00:00:00 2001 From: jce Date: Thu, 31 Aug 2023 15:04:58 +0200 Subject: [PATCH 10/12] Improve wording --- mlx/robot2rst.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mlx/robot2rst.py b/mlx/robot2rst.py index 49598b3..eecd224 100644 --- a/mlx/robot2rst.py +++ b/mlx/robot2rst.py @@ -98,8 +98,8 @@ def main(): help="Zero or more Python regexes for matching tags to treat them as traceable targets via a " "relationship. All tags get matched by default.") parser.add_argument("--include", nargs='*', default=[], - help="Zero or more Python regexes for matching tags to filter test cases. A test case is " - "included if every regex matches at least one of its tags.") + help="Zero or more Python regexes for matching tags to filter test cases. " + "If every regex matches at least one of a test case's tags, the test case is included.") parser.add_argument("-c", "--coverage", nargs='*', help="Minimum coverage percentages for the item-matrix(es); 1 value per tag in -t, --tags.") parser.add_argument("--type", default='q', From 0b878ef214f6ba10eed90b32ad903106749db8c7 Mon Sep 17 00:00:00 2001 From: jce Date: Thu, 31 Aug 2023 15:36:33 +0200 Subject: [PATCH 11/12] No longer generate RST output when no test case is itemized --- mlx/robot2rst.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/mlx/robot2rst.py b/mlx/robot2rst.py index eecd224..b973cf4 100644 --- a/mlx/robot2rst.py +++ b/mlx/robot2rst.py @@ -142,8 +142,16 @@ def main(): parser = ParserApplication(Path(args.robot_file), args.include) parser.run() - return generate_robot_2_rst(parser, Path(args.rst_file), prefix, relationship_config, - gen_matrix, test_type=test_type, only=args.expression, coverages=coverages) + if parser.tests: + exit_code = generate_robot_2_rst(parser, Path(args.rst_file), prefix, relationship_config, + gen_matrix, test_type=test_type, only=args.expression, coverages=coverages) + else: + msg = f"robot2rst did not generate {args.rst_file} because {args.robot_file} does not contain any test cases" + if args.include: + msg += f" with tags matching all regexes {args.include}" + LOGGER.info(msg) + exit_code = 0 + return exit_code def entrypoint(): From cbd3faa392df9d375b2fb2b37b115fecaf8c6945 Mon Sep 17 00:00:00 2001 From: jce Date: Thu, 31 Aug 2023 15:46:09 +0200 Subject: [PATCH 12/12] Improve wording --- README.rst | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.rst b/README.rst index 345321e..f6c2b24 100644 --- a/README.rst +++ b/README.rst @@ -59,11 +59,13 @@ Usage Name(s) of the relationship(s) used to link to items in Tags section. The default value is 'validates'. -t [TAGS ...], --tags [TAGS ...] - Regex(es) for matching tags to treat them as traceable targets via a - relationship. All tags get matched by default. + Zero or more Python regexes for matching tags to treat them as + traceable targets via a relationship. All tags get matched by + default. --include [INCLUDE ...] - Regex(es) for matching tags to filter test cases. A test case is - included if every regex matches at least one of its tags. + Zero or more Python regexes for matching tags to filter test cases. + If every regex matches at least one of a test case's tags, the test + case is included. -c [COVERAGE ...], --coverage [COVERAGE ...] Minimum coverage percentages for the item-matrix(es); 1 value per tag in -t, --tags.