Loading README.md +1 −1 Changes for README.md: 1 added line, 1 removed line. Original line number Diff line number Diff line Loading @@ -147,7 +147,7 @@ Robot Framework. Our recommendations are: - Install [Robot Framework Language Server](https://plugins.jetbrains.com/plugin/16086-robot-framework-language-server) - Define as variable the path of the working directory. In Settings > Languages & Frameworks > Robot Framework (Project), insert the following: `{"EXECDIR": "{path}/auth-test-suite"}`. (Project), insert the following: `{"EXECDIR": "{path}/ngsi-ld-test-suite"}`. ### Run configurations (PyCharm) Loading doc/analysis/generaterobotdata.py +25 −18 Changes for doc/analysis/generaterobotdata.py: 25 added lines, 18 removed lines. Original line number Diff line number Diff line from os.path import dirname from robot.api import TestSuiteBuilder from analysis.parserobotfile import ParseRobotFile from analysis.parseapiutilsfile import ParseApiUtilsFile from analysis.parsevariablesfile import ParseVariablesFile from analysis.initial_setup import InitialSetup from doc.analysis.parserobotfile import ParseRobotFile from doc.analysis.parseapiutilsfile import ParseApiUtilsFile from doc.analysis.parsevariablesfile import ParseVariablesFile from doc.analysis.initial_setup import InitialSetup from re import match, findall, finditer, sub, MULTILINE Loading Loading @@ -102,7 +102,6 @@ class GenerateRobotData: self.initial_setup = InitialSetup() def get_info(self): self.test_suite['robotpath'] = (self.robot_file.replace(f'{self.execdir}/TP/NGSI-LD/', '') .replace(f'/{self.robot.test_suite}.robot', '')) Loading Loading @@ -131,7 +130,8 @@ class GenerateRobotData: print(f'Something went wrong, the test suite {self.suite.resource.source} ' f'has different "setup" values for its test cases.') def get_permutation_keys(self, data): @staticmethod def get_permutation_keys(data): all_keys = set().union(*data) excluded_keys = ['doc', 'permutation_tp_id', 'setup', 'teardown', 'name', 'tags'] all_keys = [x for x in all_keys if x not in excluded_keys] Loading @@ -154,7 +154,7 @@ class GenerateRobotData: def get_params(self, test_case: str): test_case = self.get_data_template(string=test_case) lines_starting_response = findall(r'^\s*\$\{response\}.*|^\s*\$\{notification\}.*', test_case, MULTILINE) lines_starting_response = findall(r'^\s*\$\{response}.*|^\s*\$\{notification}.*', test_case, MULTILINE) # If there is more than one line, it means that the test case has several operations, all of them to # create the environment content to execute the last one, which is the correct one to test the Test Case Loading @@ -171,7 +171,7 @@ class GenerateRobotData: aux = [x for x in aux if x != ''] params = list() request = str() request = list() # Get the list of params of the function, they are the keys if ' ... ' in aux[1]: Loading @@ -181,7 +181,7 @@ class GenerateRobotData: # We are in the case that the attributes are in following lines for i in range(1, len(aux)): if ' ... ' in aux[i]: regex = '(\s{4})*\s{4}\.{3}\s{4}(.*)' regex = r'(\s{4})*\s{4}\.{3}\s{4}(.*)' param = match(pattern=regex, string=aux[i]) if aux: params.append(param.groups()[1]) Loading @@ -193,8 +193,8 @@ class GenerateRobotData: matches = finditer(regex, response_to_check, MULTILINE) request = aux[0].split(' ')[2] # We have two options from here, or the parameters are defined in the same line or the parameters are defined in # following lines, next lines # We have two options from here, or the parameters are defined in the same line or the parameters are # defined in following lines, next lines for a_match in matches: # Check that we have 1 group matched if len(a_match.groups()) == 1: Loading @@ -215,6 +215,9 @@ class GenerateRobotData: request, params = self.get_params(test_case=string) verb = str() query_param = str() url = str() for data in self.apiutils: verb, url, query_param = data.get_response(keyword=request) if verb != '': Loading Loading @@ -245,6 +248,7 @@ class GenerateRobotData: key = header_key[0] value = self.get_header_value(key=key) else: aux = list() # 2nd case, maybe the params are defined in the way <param>=<value> for k in self.headers: aux = [x for x in params if k in x] Loading @@ -270,7 +274,7 @@ class GenerateRobotData: def get_values_url(self, keys: list, query_param: bool, request: str, params: list) -> str: data = [self.get_value_url(key=x, request=request, params=params) for x in keys] if query_param == False: if not query_param: data = '/'.join(data).replace('//', '/').replace('?/', '?') else: aux = '/'.join(data[:-1]).replace('//', '/').replace('?/', '?') Loading Loading @@ -374,6 +378,8 @@ class GenerateRobotData: tp_id = self.generate_name() reference, pics = self.generate_reference(version=version) # TODO: robotframework==7.0 has not property keywords in the class TestSuite(), we can get the data from # [x.to_dict()['name'] for x in list(self.suite.resource.keywords)] but with some differences in execution code self.test_suite = { 'tp_id': tp_id, 'test_objective': self.suite.doc, Loading @@ -381,7 +387,8 @@ class GenerateRobotData: 'config_id': str(), 'parent_release': version, 'pics_selection': pics, 'keywords': [str(x) for x in self.suite.keywords], # 'keywords': [str(x) for x in self.suite.keywords], 'keywords': [x.to_dict()['name'] for x in list(self.suite.resource.keywords)], 'teardown': str(self.suite.teardown), 'initial_condition': str(), 'test_cases': list() Loading Loading @@ -493,7 +500,6 @@ class GenerateRobotData: self.args = dict() _ = [self.args.update(x) for x in args] template_name = list(set([list(x.keywords)[0].name for x in self.suite.tests]))[0] # Due to the information of the tags are contained in the Keyword description of the template, we need to Loading Loading @@ -534,7 +540,8 @@ class GenerateRobotData: return reference, pics def get_substring(self, string: str, key: str): @staticmethod def get_substring(string: str, key: str): pos1 = string.find(key) - 1 pos2 = string[pos1:].find('\n') result = string[pos1:pos1+pos2].split(' ') Loading @@ -545,15 +552,15 @@ class GenerateRobotData: # check_tags = all(item == tags[0] for item in tags) # # if check_tags is False or len(tags) == 0: # raise Exception(f'ERROR: the Test Suite {{self.suite.name}} has different clauses or no clauses (Tags): {tags}\n' # f'Unable to select the corresponding Reference of this Test Suite') # raise Exception(f'ERROR: the Test Suite {{self.suite.name}} has different clauses or no clauses (Tags): ' # f'{tags}\nUnable to select the corresponding Reference of this Test Suite') # else: # # All the clauses are the same, so we select the first one # reference = f'{{self.references[version]}}{tags[0].replace("_", ".")}' # pics = f'PICS_{tags[0]}' # # return reference, pics aux = [x for x in tags if match(pattern='^(\d+_\d+_\d+)', string=x)] aux = [x for x in tags if match(pattern=r'^(\d+_\d+_\d+)', string=x)] if len(aux) == 0: raise Exception( Loading doc/analysis/initial_setup.py +9 −3 Changes for doc/analysis/initial_setup.py: 9 added lines, 3 removed lines. Original line number Diff line number Diff line Loading @@ -227,12 +227,12 @@ class InitialSetup: if len(deleted_setup) != 0: print(f" WARNING: Some of the Setup functions were deleted:\n{deleted_setup}") else: print(" INFO: All current Setup functions are used in the Robot files") print(f" INFO: All current Setup functions are used in the Robot files") if len(not_included_keys) != 0: print(f" ERROR: Some Setup functions are not include in the Class:\n{not_included_keys}") else: print(" INFO: All the current Setup functions used in Robot files are included in the Class") print(f" INFO: All the current Setup functions used in Robot files are included in the Class") print() Loading Loading @@ -264,13 +264,19 @@ class InitialSetup: def get_initial_condition(self, initial_condition: str) -> str: try: return self.init[initial_condition] if initial_condition is not None: data = self.init[initial_condition] else: data = '''with { the SUT containing an initial state }''' except KeyError: print(f"ERROR: the initial condition '{initial_condition}' is not defined in the dictionary. " f"Please check it and add the new initial condition.") data = '''with { the SUT containing an initial state }''' return data Loading doc/analysis/parseapiutilsfile.py +8 −9 Changes for doc/analysis/parseapiutilsfile.py: 8 added lines, 9 removed lines. Original line number Diff line number Diff line Loading @@ -21,10 +21,9 @@ class ParseApiUtilsFile: string = string[index:] string = string.split('\n') index = None for i, item in enumerate(string): if 'response' in item: regex = "\s{4}\$\{response\}=\s{4}(POST|GET|PUT|PATCH|DELETE).*" regex = r"\s{4}\$\{response\}=\s{4}(POST|GET|PUT|PATCH|DELETE).*" match = re.match(pattern=regex, string=item) if match: Loading @@ -35,8 +34,8 @@ class ParseApiUtilsFile: return verb, url, query_param @staticmethod def get_url_request(url: str) -> list: # We have two options, the url is defined in the same line of the response or it is defined in the following def get_url_request(url: str) -> [list, bool]: # We have two options, the url is defined in the same line of the response, or it is defined in the following # lines with '...' keys = list() parameters = list() Loading @@ -57,7 +56,7 @@ class ParseApiUtilsFile: aux = parameters[0] query_param = True keys = re.split(r'\$|/', aux) keys = re.split(r'[$/]', aux) keys = [k for k in keys if k != ''] if len(parameters) != 0: Loading @@ -68,7 +67,7 @@ class ParseApiUtilsFile: match = re.match(pattern=regex, string=url) if match: aux = match.groups()[0] keys = re.split(r'\$|/', aux) keys = re.split(r'[$/]', aux) keys = [k for k in keys if k != ''] return keys, query_param Loading @@ -81,7 +80,7 @@ class ParseApiUtilsFile: def get_variables_data_variables(self, string): # Get the simple variables from the file regex = "^(\$\{.*\})\s*(.*)\n" regex = r"^(\$\{.*\})\s*(.*)\n" matches = re.finditer(regex, string, re.MULTILINE) for match in matches: Loading @@ -94,7 +93,7 @@ class ParseApiUtilsFile: def get_variables_data_dictionaries(self, string): # Get the dictionary variables from the file regex = '(\&\{.*\})' regex = r'(\&\{.*\})' matches = re.finditer(regex, string, re.MULTILINE) for match in matches: # Check that we have two groups matched Loading @@ -109,7 +108,7 @@ class ParseApiUtilsFile: index = aux.find('\n${') aux = aux[:index + 1] regex = '\.{3}[ ]*([a-zA-Z]+)=(.*)\n' regex = r'\.{3}[ ]*([a-zA-Z]+)=(.*)\n' matches2 = re.finditer(regex, aux, re.MULTILINE) dict_values = dict() for match2 in matches2: Loading doc/analysis/parserobotfile.py +2 −2 Changes for doc/analysis/parserobotfile.py: 2 added lines, 2 removed lines. Original line number Diff line number Diff line import re import os from analysis.checks import Checks from analysis.requests import Requests from doc.analysis.checks import Checks from doc.analysis.requests import Requests class ParseRobotFile: Loading Loading
README.md +1 −1 Changes for README.md: 1 added line, 1 removed line. Original line number Diff line number Diff line Loading @@ -147,7 +147,7 @@ Robot Framework. Our recommendations are: - Install [Robot Framework Language Server](https://plugins.jetbrains.com/plugin/16086-robot-framework-language-server) - Define as variable the path of the working directory. In Settings > Languages & Frameworks > Robot Framework (Project), insert the following: `{"EXECDIR": "{path}/auth-test-suite"}`. (Project), insert the following: `{"EXECDIR": "{path}/ngsi-ld-test-suite"}`. ### Run configurations (PyCharm) Loading
doc/analysis/generaterobotdata.py +25 −18 Changes for doc/analysis/generaterobotdata.py: 25 added lines, 18 removed lines. Original line number Diff line number Diff line from os.path import dirname from robot.api import TestSuiteBuilder from analysis.parserobotfile import ParseRobotFile from analysis.parseapiutilsfile import ParseApiUtilsFile from analysis.parsevariablesfile import ParseVariablesFile from analysis.initial_setup import InitialSetup from doc.analysis.parserobotfile import ParseRobotFile from doc.analysis.parseapiutilsfile import ParseApiUtilsFile from doc.analysis.parsevariablesfile import ParseVariablesFile from doc.analysis.initial_setup import InitialSetup from re import match, findall, finditer, sub, MULTILINE Loading Loading @@ -102,7 +102,6 @@ class GenerateRobotData: self.initial_setup = InitialSetup() def get_info(self): self.test_suite['robotpath'] = (self.robot_file.replace(f'{self.execdir}/TP/NGSI-LD/', '') .replace(f'/{self.robot.test_suite}.robot', '')) Loading Loading @@ -131,7 +130,8 @@ class GenerateRobotData: print(f'Something went wrong, the test suite {self.suite.resource.source} ' f'has different "setup" values for its test cases.') def get_permutation_keys(self, data): @staticmethod def get_permutation_keys(data): all_keys = set().union(*data) excluded_keys = ['doc', 'permutation_tp_id', 'setup', 'teardown', 'name', 'tags'] all_keys = [x for x in all_keys if x not in excluded_keys] Loading @@ -154,7 +154,7 @@ class GenerateRobotData: def get_params(self, test_case: str): test_case = self.get_data_template(string=test_case) lines_starting_response = findall(r'^\s*\$\{response\}.*|^\s*\$\{notification\}.*', test_case, MULTILINE) lines_starting_response = findall(r'^\s*\$\{response}.*|^\s*\$\{notification}.*', test_case, MULTILINE) # If there is more than one line, it means that the test case has several operations, all of them to # create the environment content to execute the last one, which is the correct one to test the Test Case Loading @@ -171,7 +171,7 @@ class GenerateRobotData: aux = [x for x in aux if x != ''] params = list() request = str() request = list() # Get the list of params of the function, they are the keys if ' ... ' in aux[1]: Loading @@ -181,7 +181,7 @@ class GenerateRobotData: # We are in the case that the attributes are in following lines for i in range(1, len(aux)): if ' ... ' in aux[i]: regex = '(\s{4})*\s{4}\.{3}\s{4}(.*)' regex = r'(\s{4})*\s{4}\.{3}\s{4}(.*)' param = match(pattern=regex, string=aux[i]) if aux: params.append(param.groups()[1]) Loading @@ -193,8 +193,8 @@ class GenerateRobotData: matches = finditer(regex, response_to_check, MULTILINE) request = aux[0].split(' ')[2] # We have two options from here, or the parameters are defined in the same line or the parameters are defined in # following lines, next lines # We have two options from here, or the parameters are defined in the same line or the parameters are # defined in following lines, next lines for a_match in matches: # Check that we have 1 group matched if len(a_match.groups()) == 1: Loading @@ -215,6 +215,9 @@ class GenerateRobotData: request, params = self.get_params(test_case=string) verb = str() query_param = str() url = str() for data in self.apiutils: verb, url, query_param = data.get_response(keyword=request) if verb != '': Loading Loading @@ -245,6 +248,7 @@ class GenerateRobotData: key = header_key[0] value = self.get_header_value(key=key) else: aux = list() # 2nd case, maybe the params are defined in the way <param>=<value> for k in self.headers: aux = [x for x in params if k in x] Loading @@ -270,7 +274,7 @@ class GenerateRobotData: def get_values_url(self, keys: list, query_param: bool, request: str, params: list) -> str: data = [self.get_value_url(key=x, request=request, params=params) for x in keys] if query_param == False: if not query_param: data = '/'.join(data).replace('//', '/').replace('?/', '?') else: aux = '/'.join(data[:-1]).replace('//', '/').replace('?/', '?') Loading Loading @@ -374,6 +378,8 @@ class GenerateRobotData: tp_id = self.generate_name() reference, pics = self.generate_reference(version=version) # TODO: robotframework==7.0 has not property keywords in the class TestSuite(), we can get the data from # [x.to_dict()['name'] for x in list(self.suite.resource.keywords)] but with some differences in execution code self.test_suite = { 'tp_id': tp_id, 'test_objective': self.suite.doc, Loading @@ -381,7 +387,8 @@ class GenerateRobotData: 'config_id': str(), 'parent_release': version, 'pics_selection': pics, 'keywords': [str(x) for x in self.suite.keywords], # 'keywords': [str(x) for x in self.suite.keywords], 'keywords': [x.to_dict()['name'] for x in list(self.suite.resource.keywords)], 'teardown': str(self.suite.teardown), 'initial_condition': str(), 'test_cases': list() Loading Loading @@ -493,7 +500,6 @@ class GenerateRobotData: self.args = dict() _ = [self.args.update(x) for x in args] template_name = list(set([list(x.keywords)[0].name for x in self.suite.tests]))[0] # Due to the information of the tags are contained in the Keyword description of the template, we need to Loading Loading @@ -534,7 +540,8 @@ class GenerateRobotData: return reference, pics def get_substring(self, string: str, key: str): @staticmethod def get_substring(string: str, key: str): pos1 = string.find(key) - 1 pos2 = string[pos1:].find('\n') result = string[pos1:pos1+pos2].split(' ') Loading @@ -545,15 +552,15 @@ class GenerateRobotData: # check_tags = all(item == tags[0] for item in tags) # # if check_tags is False or len(tags) == 0: # raise Exception(f'ERROR: the Test Suite {{self.suite.name}} has different clauses or no clauses (Tags): {tags}\n' # f'Unable to select the corresponding Reference of this Test Suite') # raise Exception(f'ERROR: the Test Suite {{self.suite.name}} has different clauses or no clauses (Tags): ' # f'{tags}\nUnable to select the corresponding Reference of this Test Suite') # else: # # All the clauses are the same, so we select the first one # reference = f'{{self.references[version]}}{tags[0].replace("_", ".")}' # pics = f'PICS_{tags[0]}' # # return reference, pics aux = [x for x in tags if match(pattern='^(\d+_\d+_\d+)', string=x)] aux = [x for x in tags if match(pattern=r'^(\d+_\d+_\d+)', string=x)] if len(aux) == 0: raise Exception( Loading
doc/analysis/initial_setup.py +9 −3 Changes for doc/analysis/initial_setup.py: 9 added lines, 3 removed lines. Original line number Diff line number Diff line Loading @@ -227,12 +227,12 @@ class InitialSetup: if len(deleted_setup) != 0: print(f" WARNING: Some of the Setup functions were deleted:\n{deleted_setup}") else: print(" INFO: All current Setup functions are used in the Robot files") print(f" INFO: All current Setup functions are used in the Robot files") if len(not_included_keys) != 0: print(f" ERROR: Some Setup functions are not include in the Class:\n{not_included_keys}") else: print(" INFO: All the current Setup functions used in Robot files are included in the Class") print(f" INFO: All the current Setup functions used in Robot files are included in the Class") print() Loading Loading @@ -264,13 +264,19 @@ class InitialSetup: def get_initial_condition(self, initial_condition: str) -> str: try: return self.init[initial_condition] if initial_condition is not None: data = self.init[initial_condition] else: data = '''with { the SUT containing an initial state }''' except KeyError: print(f"ERROR: the initial condition '{initial_condition}' is not defined in the dictionary. " f"Please check it and add the new initial condition.") data = '''with { the SUT containing an initial state }''' return data Loading
doc/analysis/parseapiutilsfile.py +8 −9 Changes for doc/analysis/parseapiutilsfile.py: 8 added lines, 9 removed lines. Original line number Diff line number Diff line Loading @@ -21,10 +21,9 @@ class ParseApiUtilsFile: string = string[index:] string = string.split('\n') index = None for i, item in enumerate(string): if 'response' in item: regex = "\s{4}\$\{response\}=\s{4}(POST|GET|PUT|PATCH|DELETE).*" regex = r"\s{4}\$\{response\}=\s{4}(POST|GET|PUT|PATCH|DELETE).*" match = re.match(pattern=regex, string=item) if match: Loading @@ -35,8 +34,8 @@ class ParseApiUtilsFile: return verb, url, query_param @staticmethod def get_url_request(url: str) -> list: # We have two options, the url is defined in the same line of the response or it is defined in the following def get_url_request(url: str) -> [list, bool]: # We have two options, the url is defined in the same line of the response, or it is defined in the following # lines with '...' keys = list() parameters = list() Loading @@ -57,7 +56,7 @@ class ParseApiUtilsFile: aux = parameters[0] query_param = True keys = re.split(r'\$|/', aux) keys = re.split(r'[$/]', aux) keys = [k for k in keys if k != ''] if len(parameters) != 0: Loading @@ -68,7 +67,7 @@ class ParseApiUtilsFile: match = re.match(pattern=regex, string=url) if match: aux = match.groups()[0] keys = re.split(r'\$|/', aux) keys = re.split(r'[$/]', aux) keys = [k for k in keys if k != ''] return keys, query_param Loading @@ -81,7 +80,7 @@ class ParseApiUtilsFile: def get_variables_data_variables(self, string): # Get the simple variables from the file regex = "^(\$\{.*\})\s*(.*)\n" regex = r"^(\$\{.*\})\s*(.*)\n" matches = re.finditer(regex, string, re.MULTILINE) for match in matches: Loading @@ -94,7 +93,7 @@ class ParseApiUtilsFile: def get_variables_data_dictionaries(self, string): # Get the dictionary variables from the file regex = '(\&\{.*\})' regex = r'(\&\{.*\})' matches = re.finditer(regex, string, re.MULTILINE) for match in matches: # Check that we have two groups matched Loading @@ -109,7 +108,7 @@ class ParseApiUtilsFile: index = aux.find('\n${') aux = aux[:index + 1] regex = '\.{3}[ ]*([a-zA-Z]+)=(.*)\n' regex = r'\.{3}[ ]*([a-zA-Z]+)=(.*)\n' matches2 = re.finditer(regex, aux, re.MULTILINE) dict_values = dict() for match2 in matches2: Loading
doc/analysis/parserobotfile.py +2 −2 Changes for doc/analysis/parserobotfile.py: 2 added lines, 2 removed lines. Original line number Diff line number Diff line import re import os from analysis.checks import Checks from analysis.requests import Requests from doc.analysis.checks import Checks from doc.analysis.requests import Requests class ParseRobotFile: Loading