Example #1
0
    def load_specification(self, specification_path: str, spec_format: str):
        """
        This function will load the swagger specification using the swagger_parser.
        The function will automatically call the `_init_class_resources` after.
        :param specification_path: The path where the swagger specification is located.
        :param spec_format: The file format of the specification.
        """
        # If the swagger spec format is not specified explicitly, we try to
        # derive it from the specification path
        if not spec_format:
            filename = os.path.basename(specification_path)
            extension = filename.rsplit(".", 1)[-1]
            if extension in YAML_EXTENSIONS:
                spec_format = SPEC_YAML
            elif extension in JSON_EXTENSIONS:
                spec_format = SPEC_JSON
            else:
                raise RuntimeError("Could not infer specification format. Use "
                                   "--spec-format to specify it explicitly.")

        click.secho(f"Using spec format '{spec_format}'", fg="green")
        if spec_format == SPEC_YAML:
            with open(specification_path, "r") as f:
                self.parser = SwaggerParser(swagger_yaml=f)
        else:
            self.parser = SwaggerParser(swagger_path=specification_path)

        self._init_class_resources()
def load_spec(specification_path, spec_format=None):
    # If the swagger spec format is not specified explicitly, we try to
    # derive it from the specification path
    if not spec_format:
        filename, file_ext = os.path.splitext(specification_path)
        if file_ext in YAML_EXTENSIONS:
            spec_format = SPEC_YAML
        elif file_ext in JSON_EXTENSIONS:
            spec_format = SPEC_JSON
        else:
            raise RuntimeError(
                "Could not infer specification format from extension. Use "
                "--spec-format to specify it explicitly.")
    click.secho("Using spec format '{}'".format(spec_format), fg="green")

    parser = None

    if spec_format == SPEC_YAML:
        with open(specification_path, "r") as f:
            parser = SwaggerParser(swagger_yaml=f)
    elif spec_format == SPEC_JSON:
        parser = SwaggerParser(swagger_path=specification_path)
    else:
        raise RuntimeError("Invalid spec_format {}".format(spec_format))

    # Build (path, http_verb) => operation mapping
    api_definitions = extract_Definitions(parser)

    # self._classes = {}
    return
    for path, verbs in parser.paths.items():
        generate_ViewModel(path, verbs)
    def load_specification(self, specification_path, spec_format=None):
        # If the swagger spec format is not specified explicitly, we try to
        # derive it from the specification path
        if not spec_format:
            filename = os.path.basename(specification_path)
            extension = filename.rsplit(".", 1)[-1]
            if extension in YAML_EXTENSIONS:
                spec_format = SPEC_YAML
            elif extension in JSON_EXTENSIONS:
                spec_format = SPEC_JSON
            else:
                raise RuntimeError("Could not infer specification format. Use "
                                   "--spec-format to specify it explicitly.")

        click.secho("Using spec format '{}'".format(spec_format), fg="green")
        if spec_format == SPEC_YAML:
            with open(specification_path, "r") as f:
                self.parser = SwaggerParser(swagger_yaml=f)
        else:
            self.parser = SwaggerParser(swagger_path=specification_path)

        # Build (path, http_verb) => operation mapping
        self.PATH_VERB_OPERATION_MAP = {
            (path, http_verb): operation
            for operation, (path, http_verb,
                            tag) in self.parser.operation.items()
        }

        self._make_class_definitions()
Example #4
0
    def from_config(cls, config):
        parsed_new = SwaggerParser(swagger_path=config.new_spec)
        parsed_old = SwaggerParser(swagger_path=config.old_spec)

        cls.old_parsed = parsed_old
        cls.new_parsed = parsed_new
        cls.generate()
        return cls
    def init_app(self, app, swagger_file=None):
        if not swagger_file:
            raise Exception('Swagger file not specified')

        with open(swagger_file) as f:
            swagger_yaml = f.read()

        if not swagger_yaml:
            raise Exception('No swagger found')

        self.parser = SwaggerParser(swagger_yaml=swagger_yaml)

        for path, path_config in self.parser.paths.items():
            for method, method_config in path_config.items():
                found = False

                # print(app.url_map)
                for rule in app.url_map.iter_rules():
                    if rule.rule == path and method.upper() in rule.methods:
                        found = True
                        # print(dir(rule.map.iter_rules))

                if not found:
                    print(
                        "Warning: spec route not implemented; using example from Swagger: "
                        + method.upper() + " " + path)

                    app.add_url_rule(path,
                                     path + method,
                                     self.resolve_example(method_config),
                                     methods=[method])

        app.before_request(self.before_request)
def test_swagger():
    app = get_app()
    # test the APIs
    res = app.get('/__api__')

    # make sure it's compliant
    parser = SwaggerParser(swagger_dict=yaml.load(res.body))
    spec = parser.specification

    assert spec['info']['version'] == __version__
    assert spec['schemes'] == ['https']
    assert spec['host'] == 'localhost:80'

    _values = {
        'prod': 'firefox',
        'channel': 'beta',
        'locale': 'fr',
        'territory': 'fr',
        'dist': 'dist',
        'distver': 'distver',
        'cohort': 'default',
        'ver': '34'
    }

    # now testing that every GET endpoint is present
    for path, items in spec['paths'].items():
        for verb, options in items.items():
            if verb.upper() != 'GET':
                continue
            statuses = [
                int(st) for st in options['responses'].keys() if st != '404'
            ]
            app.get(path.format(**_values), status=statuses)
Example #7
0
    def __init__(self, swagger_address, custom_base_path=None):
        json_object = requests.get(swagger_address).json()

        if custom_base_path is not None:
            json_object[
                'basePath'] = custom_base_path + json_object['basePath']

        self.swagger = SwaggerParser(swagger_dict=json_object)
Example #8
0
 def __init__(self, path_or_url, verbose=False):
     self._content = get_content(path_or_url)
     self._parser = SwaggerParser(swagger_dict=self._content)
     self.spec = self._parser.specification
     self.session = requests.Session()
     self.verbose = verbose
     self.host = self.spec['host']
     schemes = self.spec.get('schemes', ['https'])
     self.scheme = schemes[0]
     self._operations = self._get_operations()
Example #9
0
def get_all_apis(swagger_file):
    parser = SwaggerParser(swagger_path=swagger_file)
    operation = parser.operation
    opdic = {}
    for k, v in operation.items():
        opdic[v[0]] = k.split('.')[1]
    specification = parser.specification
    basePath = specification.get('basePath')
    # print(json.dumps(specification))
    paths = specification.get('paths')
    apis = []
    # print(len(paths))
    for path, v in paths.items():
        for method, v1 in v.items():
            api = {}
            uri = basePath + path
            api['uri'] = uri
            ps = []
            # print method ,uri
            # print v1
            api['method'] = method
            api['desc'] = v1.get('summary')
            # print(v1.get('summary'))
            parameters = v1.get('parameters', [])
            for p in parameters:
                if (p.get('in') == 'body'):
                    post_ps = []
                    defi = p['schema']['$ref'].replace('#/definitions/', '')
                    definitions = specification.get('definitions').get(defi)
                    properties = definitions.get("properties")
                    for p_name, p_info in properties.items():
                        post_np = {}
                        post_np['p_name'] = p_name
                        post_np['p_type'] = p_info.get('type', 'string')
                        post_np['p_des'] = p_info.get('description', '')
                        post_np['p_in'] = 'body'
                        post_ps.append(post_np)
                    ps = ps + post_ps
                else:
                    np = {}
                    print p
                    np['p_in'] = p["in"]
                    np['p_des'] = p.get("description", "")
                    np['p_type'] = p["type"]
                    np['p_type'] = p.get("type", 'string')
                    np['p_name'] = p["name"]
                    ps.append(np)
            api['ps'] = ps
            # print len(api)
            print method, v1.get('summary')
            apis.append(api)
    print(len(apis))
    return apis
    def _load_spec(self):
        filename, file_ext = os.path.splitext(self.specification_path)
        if file_ext in YAML_EXTENSIONS:
            spec_format = SPEC_YAML
        elif file_ext in JSON_EXTENSIONS:
            spec_format = SPEC_JSON
        else:
            supported_extensions = ",".join(YAML_EXTENSIONS) + ',' + ','.join(
                JSON_EXTENSIONS)
            raise RuntimeError(
                "Could not infer specification format from extension. Supported Extensions: {}"
                .format(supported_extensions))

        click.secho("Using spec format '{}'".format(spec_format), fg="green")

        if spec_format == SPEC_YAML:
            with open(self.specification_path, "r") as f:
                self.parser = SwaggerParser(swagger_yaml=f)
        elif spec_format == SPEC_JSON:
            self.parser = SwaggerParser(swagger_path=self.specification_path)
        else:
            raise RuntimeError("Invalid spec_format {}".format(spec_format))
Example #11
0
def pytest_generate_tests(metafunc):
    if 'path' in metafunc.fixturenames:
        from swagger_parser import SwaggerParser

        parser = SwaggerParser(swagger_path='../api.yaml')

        requests = []
        for path_name, path_spec in parser.paths.iteritems():
            params = []
            for param_name, param_spec in path_spec['get']['parameters'].iteritems():
                params.append('{}={}'.format(param_name, param_spec['default']))
            requests.append('{}{}'.format(path_name, '' if not params else '?{}'.format('&'.join(params))))
        metafunc.parametrize("path", requests)
    def load_specification(self, specification_path, spec_format=None):
        # If the swagger spec format is not specified explicitly, we try to
        # derive it from the specification path
        if not spec_format:
            filename = os.path.basename(specification_path)
            extension = filename.rsplit(".", 1)[-1]
            if extension in YAML_EXTENSIONS:
                spec_format = SPEC_YAML
            elif extension in JSON_EXTENSIONS:
                spec_format = SPEC_JSON
            else:
                raise RuntimeError("Could not infer specification format. Use "
                                   "--spec-format to specify it explicitly.")

        click.secho("Using spec format '{}'".format(spec_format), fg="green")
        if spec_format == SPEC_YAML:
            with open(specification_path, "r") as f:
                self.parser = SwaggerParser(swagger_yaml=f)
        else:
            self.parser = SwaggerParser(swagger_path=specification_path)

        self._make_resource_definitions()
Example #13
0
def swagger_url_patterns(swagger_dict, function_map):

    # Init with dictionary
    parser = SwaggerParser(swagger_dict=swagger_dict)

    tree = parser

    resource_map = {}

    _parse_swagger_child(tree, resource_map)

    patterns = _generate_swagger_patterns(resource_map, function_map, tree)

    return patterns
    def generate_swagger_json(self):
        """Generate a swagger from all the apis swagger."""
        # Base swagger
        base_swagger = {
            'swagger': '2.0',
            'info': self.yaml_file.get('info'),
            'basePath': self.yaml_file.get('basePath'),
            'definitions': {},
            'paths': {}
        }

        # Merge aggregates
        self.merge_aggregates(base_swagger)

        base_swagger = self.exclude_paths(base_swagger)

        # Change operation id
        spec = {}
        uri = {}
        path_list = {}
        action_list = {}
        current_module = sys.modules[__name__]
        for path, path_spec in base_swagger['paths'].items():
            for action, action_spec in path_spec.items():
                # Generate function name and get spec and api url for the path
                func_name = uuid()
                path_list[func_name] = path
                action_list[func_name] = action
                spec[func_name], uri[func_name] = self.get_spec_from_uri(path, action)

                # Export generated function to a module level function
                setattr(current_module, func_name, self.generate_operation_id_function(spec, uri, path_list, action_list, func_name))

                # Set operationId
                action_spec['operationId'] = 'swagger_aggregator.{0}'.format(func_name)

        self.swagger_parser = SwaggerParser(swagger_dict=deepcopy(base_swagger))

        # Remove exclude_fields from swagger
        for definition_name, definition_spec in base_swagger['definitions'].items():
            if definition_name in self.yaml_file.get('exclude_fields', {}):
                for key in self.yaml_file['exclude_fields'][definition_name]:
                    if key in definition_spec['required']:
                        definition_spec['required'].remove(key)
                    if key in definition_spec['properties']:
                        del definition_spec['properties'][key]

        # Write swagger.yaml
        with open(os.path.join(os.path.dirname(os.path.realpath(self.config_file)), 'swagger.yaml'), 'w') as f:
            f.write(yaml.dump(base_swagger, default_flow_style=False))
Example #15
0
 def __init__(self, path_or_url, verbose=False, loop=None,
              stream=None):
     self._content = get_content(path_or_url)
     self._parser = SwaggerParser(swagger_dict=self._content)
     self.spec = self._parser.specification
     self.verbose = verbose
     self.host = self.spec['host']
     if 'basePath' in self.spec:
         self.host += self.spec['basePath']
     schemes = self.spec.get('schemes', ['https'])
     self.scheme = schemes[0]
     self.running = True
     self._operations = self._get_operations()
     self.session = LoggedClientSession(loop, stream, verbose=verbose)
Example #16
0
    def setUp(self):
        """
        For swagger-parser, we need to convert the yaml file to json. Create a temp file to store the converted json,
        and set up the parser
        :return:
        """
        self.fileTemp = tempfile.NamedTemporaryFile(delete=False)
        with open('../cert_issuer_identity/swagger/swagger.yaml', 'r') as f:
            doc = yaml.load(f)
        with open(self.fileTemp.name, 'w') as fp:
            json.dump(doc, fp, indent=4)
            self.fileTemp.close()

        self.parser = SwaggerParser(
            swagger_path=self.fileTemp.name)  # Init with file
Example #17
0
def swagger_stub(swagger_files_url):
    """Fixture to stub a microservice from swagger files.

    To use this fixture you need to define a swagger fixture named
    swagger_files_url with the path to your swagger files, and the url to stub.
    Then just add this fixture to your tests and your request pointing to the
    urls in swagger_files_url will be managed by the stub.

    Example:
        @pytest.fixture
        def swagger_files_url():
            return [('tests/swagger.yaml', 'http://localhost:8000')]
    """
    httpretty.enable()

    for i in swagger_files_url:  # Get all given swagger files and url
        base_url = i[1]
        s = SwaggerParser(i[0])
        swagger_url[base_url] = s

        # Register all urls
        httpretty.register_uri(httpretty.GET,
                               re.compile(base_url + r'/.*'),
                               body=get_data_from_request)

        httpretty.register_uri(httpretty.POST,
                               re.compile(base_url + r'/.*'),
                               body=get_data_from_request)

        httpretty.register_uri(httpretty.PUT,
                               re.compile(base_url + r'/.*'),
                               body=get_data_from_request)

        httpretty.register_uri(httpretty.PATCH,
                               re.compile(base_url + r'/.*'),
                               body=get_data_from_request)

        httpretty.register_uri(httpretty.DELETE,
                               re.compile(base_url + r'/.*'),
                               body=get_data_from_request)

        memory[base_url] = StubMemory(s)
        yield memory[base_url]

    # Close httpretty
    httpretty.disable()
    httpretty.reset()
Example #18
0
    def test_swagger_view(self):
        res = self.testapp.get('/__api__', status=200)
        # make sure it's compliant
        parser = SwaggerParser(swagger_dict=yaml.load(res.body))
        spec = parser.specification
        self.assertEqual(spec['info']['version'], __version__)
        self.assertEqual(spec['schemes'], ['https'])
        self.assertEqual(spec['host'], 'shavar.stage.mozaws.net')

        # now testing that every GET endpoint is present
        for path, items in spec['paths'].items():
            for verb, options in items.items():
                verb = verb.upper()
                if verb != 'GET':
                    continue
                statuses = [int(st) for st in options['responses'].keys()]
                res = self.testapp.get(path, status=statuses)
Example #19
0
 def __init__(self,
              name,
              import_name,
              swagger_spec,
              static_folder=None,
              static_url_path=None,
              template_folder=None,
              url_prefix=None,
              subdomain=None,
              url_defaults=None,
              root_path=None):
     init = super(SwaggerBlueprint, self).__init__
     init(name, import_name, static_folder, static_url_path,
          template_folder, url_prefix, subdomain, url_defaults, root_path)
     self._content = get_content(swagger_spec)
     self._parser = SwaggerParser(swagger_dict=self._content)
     self.spec = self._parser.specification
     self.ops = self._get_operations()
Example #20
0
def get_genes_from_file(target_file):

    parser = SwaggerParser(swagger_path='../swagger/swagger.json')
    paths = get_paths(parser)

    paths_dict = {}
    dict_poss_numbers, dict_poss_string = possible_values_parser.load_possible_genes_values(
        target_file)

    # Iterating over all paths (path is an structure in the swagger file)
    for path, info in paths.items():

        verbs_dict = {}
        # Iterating over all verbs
        for verb, value in info.items():
            str(verb)
            paramList = value["parameters"]

            genes_list = []
            for param in paramList:
                name = param["name"]
                required = param["required"]
                type = param["type"]

                if param["type"] == 'integer':
                    numberGen = NumberGen(name, 0, int(param["minimum"]),
                                          int(param["maximum"]),
                                          dict_poss_numbers)
                    genes_list.append(numberGen)
                if param["type"] == 'string':
                    stringGen = StringGen(name, required, "", 3,
                                          dict_poss_string)
                    genes_list.append(stringGen)

            # Adding genes list to the verbs_dict
            verbs_dict[verb] = genes_list

        # Adding genes list to the verbs_dict
        paths_dict[path] = verbs_dict

    return paths_dict
Example #21
0
    def wrapper(self, *args, **kwargs):

        yaml_file = os.path.join(os.getcwd(),
                                 'swagger_server/swagger/swagger.yaml')
        parsed_file = SwaggerParser(swagger_path=yaml_file)
        method_name = function.__name__.split('_', 1)[-1]
        _uri, _method, _tag = parsed_file.operation[method_name]
        if _method in ['POST', 'post']:
            for each_param in parsed_file.paths[_uri][_method][
                    'parameters'].keys():
                if each_param == 'body':
                    definition = parsed_file.paths[_uri][_method][
                        'parameters'][each_param]['schema']['$ref'].split(
                            '/')[-1]
                    body = parsed_file.specification['definitions'][
                        definition]['example']
                    setattr(self, 'body', body)
                if each_param == 'story_number':
                    story_number = parsed_file.paths[_uri][_method][
                        'parameters'][each_param]['x-example']
                    setattr(self, 'story_number', story_number)

        response = function(self, *args, **kwargs)
        return response
Example #22
0
def swagger_test_yield(swagger_yaml_path=None, app_url=None, authorize_error=None,
                       wait_time_between_tests=0, use_example=True, dry_run=False,
                       extra_headers={}):
    """Test the given swagger api. Yield the action and operation done for each test.

    Test with either a swagger.yaml path for a connexion app or with an API
    URL if you have a running API.

    Args:
        swagger_yaml_path: path of your YAML swagger file.
        app_url: URL of the swagger api.
        authorize_error: dict containing the error you don't want to raise.
                         ex: {
                            'get': {
                                '/pet/': ['404']
                            }
                         }
                         Will ignore 404 when getting a pet.
        wait_time_between_tests: an number that will be used as waiting time between tests [in seconds].
        use_example: use example of your swagger file instead of generated data.
        dry_run: don't actually execute the test, only show what would be sent
        extra_headers: additional headers you may want to send for all operations

    Returns:
        Yield between each test: (action, operation)

    Raises:
        ValueError: In case you specify neither a swagger.yaml path or an app URL.
    """
    if authorize_error is None:
        authorize_error = {}

    # Init test
    if swagger_yaml_path is not None and app_url is not None:
        app_client = requests
        swagger_parser = SwaggerParser(swagger_yaml_path, use_example=use_example)
    elif swagger_yaml_path is not None:
        specification_dir = os.path.dirname(os.path.realpath(swagger_yaml_path))
        app = connexion.App(__name__, port=8080, debug=True, specification_dir=specification_dir)
        app.add_api(os.path.basename(swagger_yaml_path))
        app_client = app.app.test_client()
        swagger_parser = SwaggerParser(swagger_yaml_path, use_example=use_example)
    elif app_url is not None:
        app_client = requests
        remote_swagger_def = requests.get(u'{0}/swagger.json'.format(app_url)).json()
        swagger_parser = SwaggerParser(swagger_dict=remote_swagger_def, use_example=use_example)
    else:
        raise ValueError('You must either specify a swagger.yaml path or an app url')

    print("Starting testrun against {0} or {1} using examples: "
          "{2}".format(swagger_yaml_path, app_url, use_example))

    operation_sorted = {method: [] for method in _HTTP_METHODS}

    # Sort operation by action
    operations = swagger_parser.operation.copy()
    operations.update(swagger_parser.generated_operation)
    for operation, request in operations.items():
        operation_sorted[request[1]].append((operation, request))

    postponed = []

    # For every operationId
    for action in _HTTP_METHODS:
        for operation in operation_sorted[action]:
            # Make request
            path = operation[1][0]
            action = operation[1][1]
            client_name = getattr(app_client, '__name__', 'FlaskClient')

            request_args = get_request_args(path, action, swagger_parser)
            url, body, headers, files = get_url_body_from_request(action, path, request_args, swagger_parser)

            logger.info(u'TESTING {0} {1}'.format(action.upper(), url))

            # Add any extra headers specified by the user
            headers.extend([(key, value)for key, value in extra_headers.items()])

            if swagger_yaml_path is not None and app_url is None:
                if dry_run:
                    logger.info("\nWould send %s to %s with body %s and headers %s" %
                                (action.upper(), url, body, headers))
                    continue
                response = get_method_from_action(app_client, action)(url, headers=headers, data=body)
            else:
                if app_url.endswith(swagger_parser.base_path):
                    base_url = app_url[:-len(swagger_parser.base_path)]
                else:
                    base_url = app_url
                full_path = u'{0}{1}'.format(base_url, url)
                if dry_run:
                    logger.info("\nWould send %s to %s with body %s and headers %s" %
                                (action.upper(), full_path, body, headers))
                    continue
                response = get_method_from_action(app_client, action)(full_path,
                                                                      headers=dict(headers),
                                                                      data=body,
                                                                      files=files)

            logger.info(u'Using {0}, got status code {1} for ********** {2} {3}'.format(
                client_name, response.status_code, action.upper(), url))

            # Check if authorize error
            if (action in authorize_error and path in authorize_error[action] and
                    response.status_code in authorize_error[action][path]):
                logger.info(u'Got expected authorized error on {0} with status {1}'.format(url, response.status_code))
                yield (action, operation)
                continue

            if response.status_code is not 404:
                # Get valid request and response body
                body_req = swagger_parser.get_send_request_correct_body(path, action)

                try:
                    response_spec = swagger_parser.get_request_data(path, action, body_req)
                except (TypeError, ValueError) as exc:
                    logger.warning(u'Error in the swagger file: {0}'.format(repr(exc)))
                    continue

                # Get response data
                if hasattr(response, 'content'):
                    response_text = response.content
                else:
                    response_text = response.data

                # Convert to str
                if hasattr(response_text, 'decode'):
                    response_text = response_text.decode('utf-8')

                # Get json
                try:
                    response_json = json.loads(response_text)
                except ValueError:
                    response_json = response_text

                if response.status_code in response_spec.keys():
                    validate_definition(swagger_parser, response_spec[response.status_code], response_json)
                elif 'default' in response_spec.keys():
                    validate_definition(swagger_parser, response_spec['default'], response_json)
                else:
                    raise AssertionError('Invalid status code {0}. Expected: {1}'.format(response.status_code,
                                                                                         response_spec.keys()))

                if wait_time_between_tests > 0:
                    time.sleep(wait_time_between_tests)

                yield (action, operation)
            else:
                # 404 => Postpone retry
                if {'action': action, 'operation': operation} in postponed:  # Already postponed => raise error
                    raise Exception(u'Invalid status code {0}'.format(response.status_code))

                operation_sorted[action].append(operation)
                postponed.append({'action': action, 'operation': operation})
                yield (action, operation)
                continue
Example #23
0
 def swagger_parser(self):
     swagger_dict = load_dict_from_path(self.swagger_path)
     return SwaggerParser(swagger_dict=swagger_dict)
Example #24
0
def swagger_parser():
    return SwaggerParser('tests/swagger.yaml')
Example #25
0
def swagger_file_parser(request):
    return SwaggerParser(request.param)
Example #26
0
def swagger_array_parser():
    return SwaggerParser('tests/swagger_arrays.yaml')
Example #27
0
def inline_parser():
    return SwaggerParser('tests/inline.yaml')
Example #28
0
import swagger_parser.SwaggerParser as s

a = s.SwaggerParser('swagger.json')

a.generate_datastructs()
# -*- coding: utf-8 -*-
from swagger_parser import SwaggerParser

parser = SwaggerParser(swagger_path='https://petstore.swagger.io/v2/swagger.json')

print(parser)

Example #30
0
def swagger_test_yield(swagger_yaml_path=None, app_url=None, authorize_error=None,
                       wait_between_test=False, use_example=True):
    """Test the given swagger api. Yield the action and operation done for each test.

    Test with either a swagger.yaml path for a connexion app or with an API
    URL if you have a running API.

    Args:
        swagger_yaml_path: path of your YAML swagger file.
        app_url: URL of the swagger api.
        authorize_error: dict containing the error you don't want to raise.
                         ex: {
                            'get': {
                                '/pet/': ['404']
                            }
                         }
                         Will ignore 404 when getting a pet.
        wait_between_test: wait between tests (useful if you use Elasticsearch).
        use_example: use example of your swagger file instead of generated data.

    Returns:
        Yield between each test: (action, operation)

    Raises:
        ValueError: In case you specify neither a swagger.yaml path or an app URL.
    """
    if authorize_error is None:
        authorize_error = {}

    # Init test
    if swagger_yaml_path is not None:
        app = connexion.App(__name__, port=8080, debug=True, specification_dir=os.path.dirname(os.path.realpath(swagger_yaml_path)))
        app.add_api(os.path.basename(swagger_yaml_path))
        app_client = app.app.test_client()
        swagger_parser = SwaggerParser(swagger_yaml_path, use_example=use_example)
    elif app_url is not None:
        app_client = requests
        swagger_parser = SwaggerParser(swagger_dict=requests.get(u'{0}/swagger.json'.format(app_url)).json(),
                                       use_example=False)
    else:
        raise ValueError('You must either specify a swagger.yaml path or an app url')

    operation_sorted = {'post': [], 'get': [], 'put': [], 'patch': [], 'delete': []}

    # Sort operation by action
    for operation, request in swagger_parser.operation.items():
        operation_sorted[request[1]].append((operation, request))

    postponed = []

    # For every operationId
    for action in ['post', 'get', 'put', 'patch', 'delete']:
        for operation in operation_sorted[action]:
            # Make request
            path = operation[1][0]
            action = operation[1][1]

            request_args = get_request_args(path, action, swagger_parser)
            url, body, headers, files = get_url_body_from_request(action, path, request_args, swagger_parser)

            logger.info(u'TESTING {0} {1}'.format(action.upper(), url))

            if swagger_yaml_path is not None:
                response = get_method_from_action(app_client, action)(url, headers=headers,
                                                                      data=body)
            else:
                response = get_method_from_action(app_client, action)(u'{0}{1}'.format(app_url.replace(swagger_parser.base_path, ''), url),
                                                                      headers=dict(headers),
                                                                      data=body,
                                                                      files=files)

            logger.info(u'Got status code: {0}'.format(response.status_code))

            # Check if authorize error
            if (action in authorize_error and path in authorize_error[action] and
                    response.status_code in authorize_error[action][path]):
                logger.info(u'Got authorized error on {0} with status {1}'.format(url, response.status_code))
                yield (action, operation)
                continue

            if not response.status_code == 404:
                # Get valid request and response body
                body_req = swagger_parser.get_send_request_correct_body(path, action)

                try:
                    response_spec = swagger_parser.get_request_data(path, action, body_req)
                except (TypeError, ValueError) as exc:
                    logger.warning(u'Error in the swagger file: {0}'.format(repr(exc)))
                    continue

                # Get response data
                if hasattr(response, 'content'):
                    response_text = response.content
                else:
                    response_text = response.data

                # Convert to str
                if hasattr(response_text, 'decode'):
                    response_text = response_text.decode('utf-8')

                # Get json
                try:
                    response_json = json.loads(response_text)
                except ValueError:
                    response_json = response_text

                assert response.status_code < 400

                if response.status_code in response_spec.keys():
                    validate_definition(swagger_parser, response_spec[response.status_code], response_json)
                elif 'default' in response_spec.keys():
                    validate_definition(swagger_parser, response_spec['default'], response_json)
                else:
                    raise AssertionError('Invalid status code {0}. Expected: {1}'.format(response.status_code,
                                                                                         response_spec.keys()))

                if wait_between_test:  # Wait
                    time.sleep(2)

                yield (action, operation)
            else:
                # 404 => Postpone retry
                if {'action': action, 'operation': operation} in postponed:  # Already postponed => raise error
                    raise Exception(u'Invalid status code {0}'.format(response.status_code))

                operation_sorted[action].append(operation)
                postponed.append({'action': action, 'operation': operation})
                yield (action, operation)
                continue