diff --git a/lobster/tools/cpptest/cpptest.py b/lobster/tools/cpptest/cpptest.py index 5b2bc30a..f1b564f2 100644 --- a/lobster/tools/cpptest/cpptest.py +++ b/lobster/tools/cpptest/cpptest.py @@ -17,13 +17,12 @@ # License along with this program. If not, see # . -import json import sys import argparse import os.path from copy import copy from enum import Enum - +import yaml from lobster.items import Tracing_Tag, Activity from lobster.location import File_Reference from lobster.io import lobster_write @@ -66,19 +65,19 @@ class RequirementTypes(Enum): def parse_config_file(file_name: str) -> dict: """ - Parse the configuration dictionary from given config file. + Parse the configuration dictionary from the given YAML config file. - The configuration dictionary for cpptest must contain the OUTPUT and - CODEBEAMER_URL keys. - Each output configuration dictionary contains a file name as key and - a value dictionary containing the keys MARKERS and KIND. - The supported values for the MARKERS list are specified in + The configuration dictionary for cpptest must contain the `output` and + `codebeamer_url` keys. + Each output configuration dictionary contains a file name as a key and + a value dictionary containing the keys `markers` and `kind`. + The supported values for the `markers` list are specified in SUPPORTED_REQUIREMENTS. Parameters ---------- file_name : str - The file name of the cpptest config file. + The file name of the cpptest YAML config file. Returns ------- @@ -88,17 +87,17 @@ def parse_config_file(file_name: str) -> dict: Raises ------ Exception - If the config dict does not contain the required keys - or contains not supported values. + If the config dictionary does not contain the required keys + or is improperly formatted. """ if not os.path.isfile(file_name): raise ValueError(f'{file_name} is not an existing file!') with open(file_name, "r", encoding='utf-8') as file: - config_dict: dict = json.loads(file.read()) + config_dict = yaml.safe_load(file) - if (OUTPUT not in config_dict.keys() or - CODEBEAMER_URL not in config_dict.keys()): + if (not config_dict or OUTPUT not in config_dict or + CODEBEAMER_URL not in config_dict): raise ValueError(f'Please follow the right config file structure! ' f'Missing attribute "{OUTPUT}" and ' f'"{CODEBEAMER_URL}"') @@ -107,17 +106,16 @@ def parse_config_file(file_name: str) -> dict: supported_markers = ', '.join(SUPPORTED_REQUIREMENTS) for output_file, output_file_config_dict in output_config_dict.items(): - if MARKERS not in output_file_config_dict.keys(): + if MARKERS not in output_file_config_dict: raise ValueError(f'Please follow the right config file structure! ' f'Missing attribute "{MARKERS}" for output file ' f'"{output_file}"') - if KIND not in output_file_config_dict.keys(): + if KIND not in output_file_config_dict: raise ValueError(f'Please follow the right config file structure! ' f'Missing attribute "{KIND}" for output file ' f'"{output_file}"') - output_file_marker_list = output_file_config_dict.get(MARKERS) - for output_file_marker in output_file_marker_list: + for output_file_marker in output_file_config_dict.get(MARKERS, []): if output_file_marker not in SUPPORTED_REQUIREMENTS: raise ValueError(f'"{output_file_marker}" is not a supported ' f'"{MARKERS}" value ' @@ -377,20 +375,18 @@ def main(): and launch lobster_cpptest. """ # lobster-trace: cpptest_req.Dummy_Requirement - ap.add_argument("files", - nargs="+", - metavar="FILE|DIR") - ap.add_argument("--config-file", - help="path of the config file, it consists of " - "a requirement types as keys and " - "output filenames as value", - required=True, - default=None) + ap.add_argument("--config", + help=("Path to YAML file with arguments, " + "by default (cpptest-config.yaml)"), + default="cpptest-config.yaml") options = ap.parse_args() try: - config_dict = parse_config_file(options.config_file) + config_dict = parse_config_file(options.config) + + options.files = config_dict.get("files", ["."]) + config_dict.pop("files", None) lobster_cpptest( file_dir_list=options.files, diff --git a/packages/lobster-tool-cpptest/README.md b/packages/lobster-tool-cpptest/README.md index bd32c6e7..2abbaa6f 100644 --- a/packages/lobster-tool-cpptest/README.md +++ b/packages/lobster-tool-cpptest/README.md @@ -11,8 +11,13 @@ markers in the comments of the source code. ## Tools -* `lobster-cpptest`: Extract requirements with specific references - from tests. +* `lobster-cpptest`: Extract requirements with dynamic refrences + from comments. + +## Configuration + +The tool requires a YAML configuration file to define its settings. +You must provide this file when running the tool to specify parameters to process. ## Usage @@ -31,44 +36,37 @@ For this you have to provide a C/C++ test documentation with `markers`: */ TEST(RequirementTagTest1, RequirementsAsMultipleComments) {} ``` -You have to provide a config-file which determines which `markers` should be extracted in which output-files. -The expected `kind` for each output-file should also be specified. +You can also provide parameters to specify which markers should be extracted from which files. +Additionally, you need to provide the Codebeamer URL. -* Note: If you want to extract the other tests with other `markers`, - you can use an empty list as `markers` value. Be aware in this case the tests do not have any references. +Examples: +```yaml + output: + component_tests.lobster: + markers: + - "@requirement" + kind: "req" -```config -{ - "markers": [], - "kind": "req" -} -``` + unit_tests.lobster: + markers: + - "@requiredby" + kind: "req" -In addition, you have to provide the codebeamer-url: - -`Kind` can be either `req`, `imp` or `act`. - -```config -{ - "output": { - "unit_tests.lobster" : - { - "markers": ["@requirement"], - "kind": "req" - }, - "components_tests.lobster" : - { - "markers": ["@requiredby", "@requirement"], - "kind": "imp" - } - }, - "codebeamer_url": "https://codebeamer.example.com/test" -} - ``` + other_tests.lobster: + markers: [] + kind: "" -For more information about how to setup cpp and config files take a look at [manual-lobster_cpptest](../../documentation/manual-lobster_cpptest.md) + codebeamer_url: "https://codebeamer.com" + ``` +You can also include CPP files in the YAML configuration file. +```yaml + files: + - 'path/to/source1.cpp' + - 'path/to/source2.cpp' +``` +Note: File paths are accepted only in single quotes. ## Copyright & License information diff --git a/tests-unit/lobster-cpptest/data/cpptest-config_1.yaml b/tests-unit/lobster-cpptest/data/cpptest-config_1.yaml new file mode 100644 index 00000000..b485e363 --- /dev/null +++ b/tests-unit/lobster-cpptest/data/cpptest-config_1.yaml @@ -0,0 +1,11 @@ +output: + component_tests.lobster: + markers: ["@requirement", "@requiredby"] + kind: "req" + + other_tests.lobster: + markers: [] + + kind: "" + +codebeamer_url: "https://codebeamer.com" diff --git a/tests-unit/lobster-cpptest/data/cpptest-config_2.yaml b/tests-unit/lobster-cpptest/data/cpptest-config_2.yaml new file mode 100644 index 00000000..b50c1c2f --- /dev/null +++ b/tests-unit/lobster-cpptest/data/cpptest-config_2.yaml @@ -0,0 +1,17 @@ +output: + component_tests.lobster: + markers: + - "@requirement" + kind: "req" + + unit_tests.lobster: + markers: + - "@requiredby" + kind: "req" + + other_tests.lobster: + markers: [] + + kind: "" + +codebeamer_url: "https://codebeamer.com" \ No newline at end of file diff --git a/tests-unit/lobster-cpptest/test_cpptest.py b/tests-unit/lobster-cpptest/test_cpptest.py index 373082ce..adcd0ea4 100644 --- a/tests-unit/lobster-cpptest/test_cpptest.py +++ b/tests-unit/lobster-cpptest/test_cpptest.py @@ -22,6 +22,8 @@ def setUp(self): self.test_case_file = str(Path(dirname(__file__), "data", "test_case.cpp")) self.test_config_1 = str(Path(dirname(__file__), "data", "test_1.config")) self.test_config_2 = str(Path(dirname(__file__), "data", "test_2.config")) + self.test_config_3 = str(Path(dirname(__file__), "data", "cpptest-config_1.yaml")) + self.test_config_4 = str(Path(dirname(__file__), "data", "cpptest-config_2.yaml")) self.req_test_type = [RequirementTypes.REQS.value] self.req_by_test_type = [RequirementTypes.REQ_BY.value] @@ -46,7 +48,7 @@ def setUp(self): self.component_test_lobster_file, self.other_test_lobster_file] def test_parse_config_file_with_two_markers_for_two_outputs(self): - config_dict = parse_config_file(self.test_config_1) + config_dict = parse_config_file(self.test_config_4) self.assertIsNotNone(config_dict) self.assertIsInstance(config_dict, dict) self.assertEqual(2, len(config_dict)) @@ -114,7 +116,7 @@ def test_parse_config_file_with_two_markers_for_two_outputs(self): self.assertEqual('', other_test_kind_value) def test_parse_config_file_with_two_markers_for_one_output(self): - config_dict = parse_config_file(self.test_config_2) + config_dict = parse_config_file(self.test_config_3) self.assertIsNotNone(config_dict) self.assertIsInstance(config_dict, dict) self.assertEqual(2, len(config_dict)) @@ -314,7 +316,7 @@ def test_not_existing_file_dir(self): def test_separate_output_config(self): file_dir_list = [self.test_case_file] - config_dict: dict = parse_config_file(self.test_config_1) + config_dict: dict = parse_config_file(self.test_config_4) lobster_cpptest( file_dir_list=file_dir_list,