Commit a579aead authored by lopezaguilar's avatar lopezaguilar
Browse files

Update keywords generation and update robotframework-tidy package

parent 0da19e39
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -147,7 +147,7 @@ Robot Framework. Our recommendations are:
- Install [Robot Framework Language Server](https://plugins.jetbrains.com/plugin/16086-robot-framework-language-server)
- 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 
- 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)
### Run configurations (PyCharm)
+28 −21
Original line number Original line Diff line number Diff line
from os.path import dirname
from os.path import dirname
from robot.api import TestSuiteBuilder
from robot.api import TestSuiteBuilder
from analysis.parserobotfile import ParseRobotFile
from doc.analysis.parserobotfile import ParseRobotFile
from analysis.parseapiutilsfile import ParseApiUtilsFile
from doc.analysis.parseapiutilsfile import ParseApiUtilsFile
from analysis.parsevariablesfile import ParseVariablesFile
from doc.analysis.parsevariablesfile import ParseVariablesFile
from analysis.initial_setup import InitialSetup
from doc.analysis.initial_setup import InitialSetup
from re import match, findall, finditer, sub, MULTILINE
from re import match, findall, finditer, sub, MULTILINE




@@ -102,7 +102,6 @@ class GenerateRobotData:


        self.initial_setup = InitialSetup()
        self.initial_setup = InitialSetup()



    def get_info(self):
    def get_info(self):
        self.test_suite['robotpath'] = (self.robot_file.replace(f'{self.execdir}/TP/NGSI-LD/', '')
        self.test_suite['robotpath'] = (self.robot_file.replace(f'{self.execdir}/TP/NGSI-LD/', '')
                                        .replace(f'/{self.robot.test_suite}.robot', ''))
                                        .replace(f'/{self.robot.test_suite}.robot', ''))
@@ -131,7 +130,8 @@ class GenerateRobotData:
            print(f'Something went wrong, the test suite {self.suite.resource.source} '
            print(f'Something went wrong, the test suite {self.suite.resource.source} '
                  f'has different "setup" values for its test cases.')
                  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)
        all_keys = set().union(*data)
        excluded_keys = ['doc', 'permutation_tp_id', 'setup', 'teardown', 'name', 'tags']
        excluded_keys = ['doc', 'permutation_tp_id', 'setup', 'teardown', 'name', 'tags']
        all_keys = [x for x in all_keys if x not in excluded_keys]
        all_keys = [x for x in all_keys if x not in excluded_keys]
@@ -154,7 +154,7 @@ class GenerateRobotData:


    def get_params(self, test_case: str):
    def get_params(self, test_case: str):
        test_case = self.get_data_template(string=test_case)
        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
        # 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
        # create the environment content to execute the last one, which is the correct one to test the Test Case
@@ -171,7 +171,7 @@ class GenerateRobotData:
        aux = [x for x in aux if x != '']
        aux = [x for x in aux if x != '']


        params = list()
        params = list()
        request = str()
        request = list()


        # Get the list of params of the function, they are the keys
        # Get the list of params of the function, they are the keys
        if '    ...    ' in aux[1]:
        if '    ...    ' in aux[1]:
@@ -181,7 +181,7 @@ class GenerateRobotData:
            # We are in the case that the attributes are in following lines
            # We are in the case that the attributes are in following lines
            for i in range(1, len(aux)):
            for i in range(1, len(aux)):
                if '    ...    ' in aux[i]:
                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])
                    param = match(pattern=regex, string=aux[i])
                    if aux:
                    if aux:
                        params.append(param.groups()[1])
                        params.append(param.groups()[1])
@@ -193,8 +193,8 @@ class GenerateRobotData:
            matches = finditer(regex, response_to_check, MULTILINE)
            matches = finditer(regex, response_to_check, MULTILINE)
            request = aux[0].split('    ')[2]
            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
            # We have two options from here, or the parameters are defined in the same line or the parameters are
            # following lines, next lines
            # defined in following lines, next lines
            for a_match in matches:
            for a_match in matches:
                # Check that we have 1 group matched
                # Check that we have 1 group matched
                if len(a_match.groups()) == 1:
                if len(a_match.groups()) == 1:
@@ -215,6 +215,9 @@ class GenerateRobotData:


        request, params = self.get_params(test_case=string)
        request, params = self.get_params(test_case=string)


        verb = str()
        query_param = str()
        url = str()
        for data in self.apiutils:
        for data in self.apiutils:
            verb, url, query_param = data.get_response(keyword=request)
            verb, url, query_param = data.get_response(keyword=request)
            if verb != '':
            if verb != '':
@@ -245,6 +248,7 @@ class GenerateRobotData:
            key = header_key[0]
            key = header_key[0]
            value = self.get_header_value(key=key)
            value = self.get_header_value(key=key)
        else:
        else:
            aux = list()
            # 2nd case, maybe the params are defined in the way <param>=<value>
            # 2nd case, maybe the params are defined in the way <param>=<value>
            for k in self.headers:
            for k in self.headers:
                aux = [x for x in params if k in x]
                aux = [x for x in params if k in x]
@@ -270,7 +274,7 @@ class GenerateRobotData:
    def get_values_url(self, keys: list, query_param: bool, request: str, params: list) -> str:
    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]
        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('?/', '?')
            data = '/'.join(data).replace('//', '/').replace('?/', '?')
        else:
        else:
            aux = '/'.join(data[:-1]).replace('//', '/').replace('?/', '?')
            aux = '/'.join(data[:-1]).replace('//', '/').replace('?/', '?')
@@ -374,6 +378,8 @@ class GenerateRobotData:
        tp_id = self.generate_name()
        tp_id = self.generate_name()
        reference, pics = self.generate_reference(version=version)
        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 = {
        self.test_suite = {
            'tp_id': tp_id,
            'tp_id': tp_id,
            'test_objective': self.suite.doc,
            'test_objective': self.suite.doc,
@@ -381,7 +387,8 @@ class GenerateRobotData:
            'config_id': str(),
            'config_id': str(),
            'parent_release': version,
            'parent_release': version,
            'pics_selection': pics,
            '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),
            'teardown': str(self.suite.teardown),
            'initial_condition': str(),
            'initial_condition': str(),
            'test_cases': list()
            'test_cases': list()
@@ -493,7 +500,6 @@ class GenerateRobotData:
        self.args = dict()
        self.args = dict()
        _ = [self.args.update(x) for x in args]
        _ = [self.args.update(x) for x in args]



        template_name = list(set([list(x.keywords)[0].name for x in self.suite.tests]))[0]
        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
        # Due to the information of the tags are contained in the Keyword description of the template, we need to
@@ -534,7 +540,8 @@ class GenerateRobotData:


        return reference, pics
        return reference, pics


    def get_substring(self, string: str, key: str):
    @staticmethod
    def get_substring(string: str, key: str):
        pos1 = string.find(key) - 1
        pos1 = string.find(key) - 1
        pos2 = string[pos1:].find('\n')
        pos2 = string[pos1:].find('\n')
        result = string[pos1:pos1+pos2].split('    ')
        result = string[pos1:pos1+pos2].split('    ')
@@ -545,15 +552,15 @@ class GenerateRobotData:
        # check_tags = all(item == tags[0] for item in tags)
        # check_tags = all(item == tags[0] for item in tags)
        #
        #
        # if check_tags is False or len(tags) == 0:
        # 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'
        #     raise Exception(f'ERROR: the Test Suite {{self.suite.name}} has different clauses or no clauses (Tags): '
        #                     f'Unable to select the corresponding Reference of this Test Suite')
        #                     f'{tags}\nUnable to select the corresponding Reference of this Test Suite')
        # else:
        # else:
        #     # All the clauses are the same, so we select the first one
        #     # All the clauses are the same, so we select the first one
        #     reference = f'{{self.references[version]}}{tags[0].replace("_", ".")}'
        #     reference = f'{{self.references[version]}}{tags[0].replace("_", ".")}'
        #     pics = f'PICS_{tags[0]}'
        #     pics = f'PICS_{tags[0]}'
        #
        #
        # return reference, pics
        # 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:
        if len(aux) == 0:
            raise Exception(
            raise Exception(
+10 −4
Original line number Original line Diff line number Diff line
@@ -227,12 +227,12 @@ class InitialSetup:
        if len(deleted_setup) != 0:
        if len(deleted_setup) != 0:
            print(f"    WARNING: Some of the Setup functions were deleted:\n{deleted_setup}")
            print(f"    WARNING: Some of the Setup functions were deleted:\n{deleted_setup}")
        else:
        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:
        if len(not_included_keys) != 0:
            print(f"    ERROR: Some Setup functions are not include in the Class:\n{not_included_keys}")
            print(f"    ERROR: Some Setup functions are not include in the Class:\n{not_included_keys}")
        else:
        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()
        print()


@@ -264,13 +264,19 @@ class InitialSetup:


    def get_initial_condition(self, initial_condition: str) -> str:
    def get_initial_condition(self, initial_condition: str) -> str:
        try:
        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:
        except KeyError:
            print(f"ERROR: the initial condition '{initial_condition}' is not defined in the dictionary. "
            print(f"ERROR: the initial condition '{initial_condition}' is not defined in the dictionary. "
                  f"Please check it and add the new initial condition.")
                  f"Please check it and add the new initial condition.")
            data = '''with {
            data = '''with {
   the SUT containing an initial state
   the SUT containing an initial state
}'''
}'''

        return data
        return data




+8 −9
Original line number Original line Diff line number Diff line
@@ -21,10 +21,9 @@ class ParseApiUtilsFile:
        string = string[index:]
        string = string[index:]
        string = string.split('\n')
        string = string.split('\n')


        index = None
        for i, item in enumerate(string):
        for i, item in enumerate(string):
            if 'response' in item:
            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)
                match = re.match(pattern=regex, string=item)


                if match:
                if match:
@@ -35,8 +34,8 @@ class ParseApiUtilsFile:
        return verb, url, query_param
        return verb, url, query_param


    @staticmethod
    @staticmethod
    def get_url_request(url: str) -> list:
    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
        # We have two options, the url is defined in the same line of the response, or it is defined in the following
        # lines with '...'
        # lines with '...'
        keys = list()
        keys = list()
        parameters = list()
        parameters = list()
@@ -57,7 +56,7 @@ class ParseApiUtilsFile:
                aux = parameters[0]
                aux = parameters[0]
                query_param = True
                query_param = True


            keys = re.split(r'\$|/', aux)
            keys = re.split(r'[$/]', aux)
            keys = [k for k in keys if k != '']
            keys = [k for k in keys if k != '']


            if len(parameters) != 0:
            if len(parameters) != 0:
@@ -68,7 +67,7 @@ class ParseApiUtilsFile:
            match = re.match(pattern=regex, string=url)
            match = re.match(pattern=regex, string=url)
            if match:
            if match:
                aux = match.groups()[0]
                aux = match.groups()[0]
                keys = re.split(r'\$|/', aux)
                keys = re.split(r'[$/]', aux)
                keys = [k for k in keys if k != '']
                keys = [k for k in keys if k != '']


        return keys, query_param
        return keys, query_param
@@ -81,7 +80,7 @@ class ParseApiUtilsFile:


    def get_variables_data_variables(self, string):
    def get_variables_data_variables(self, string):
        # Get the simple variables from the file
        # Get the simple variables from the file
        regex = "^(\$\{.*\})\s*(.*)\n"
        regex = r"^(\$\{.*\})\s*(.*)\n"


        matches = re.finditer(regex, string, re.MULTILINE)
        matches = re.finditer(regex, string, re.MULTILINE)
        for match in matches:
        for match in matches:
@@ -94,7 +93,7 @@ class ParseApiUtilsFile:


    def get_variables_data_dictionaries(self, string):
    def get_variables_data_dictionaries(self, string):
        # Get the dictionary variables from the file
        # Get the dictionary variables from the file
        regex = '(\&\{.*\})'
        regex = r'(\&\{.*\})'
        matches = re.finditer(regex, string, re.MULTILINE)
        matches = re.finditer(regex, string, re.MULTILINE)
        for match in matches:
        for match in matches:
            # Check that we have two groups matched
            # Check that we have two groups matched
@@ -109,7 +108,7 @@ class ParseApiUtilsFile:
                index = aux.find('\n${')
                index = aux.find('\n${')
                aux = aux[:index + 1]
                aux = aux[:index + 1]


                regex = '\.{3}[ ]*([a-zA-Z]+)=(.*)\n'
                regex = r'\.{3}[ ]*([a-zA-Z]+)=(.*)\n'
                matches2 = re.finditer(regex, aux, re.MULTILINE)
                matches2 = re.finditer(regex, aux, re.MULTILINE)
                dict_values = dict()
                dict_values = dict()
                for match2 in matches2:
                for match2 in matches2:
+2 −2
Original line number Original line Diff line number Diff line
import re
import re
import os
import os
from analysis.checks import Checks
from doc.analysis.checks import Checks
from analysis.requests import Requests
from doc.analysis.requests import Requests




class ParseRobotFile:
class ParseRobotFile:
Loading