robotframework-openapitools 0.3.0__py3-none-any.whl → 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. OpenApiDriver/__init__.py +45 -41
  2. OpenApiDriver/openapi_executors.py +83 -49
  3. OpenApiDriver/openapi_reader.py +114 -116
  4. OpenApiDriver/openapidriver.libspec +209 -133
  5. OpenApiDriver/openapidriver.py +31 -296
  6. OpenApiLibCore/__init__.py +39 -13
  7. OpenApiLibCore/annotations.py +10 -0
  8. OpenApiLibCore/data_generation/__init__.py +10 -0
  9. OpenApiLibCore/data_generation/body_data_generation.py +250 -0
  10. OpenApiLibCore/data_generation/data_generation_core.py +233 -0
  11. OpenApiLibCore/data_invalidation.py +294 -0
  12. OpenApiLibCore/dto_base.py +75 -129
  13. OpenApiLibCore/dto_utils.py +125 -85
  14. OpenApiLibCore/localized_faker.py +88 -0
  15. OpenApiLibCore/models.py +723 -0
  16. OpenApiLibCore/oas_cache.py +14 -13
  17. OpenApiLibCore/openapi_libcore.libspec +363 -322
  18. OpenApiLibCore/openapi_libcore.py +388 -1903
  19. OpenApiLibCore/parameter_utils.py +97 -0
  20. OpenApiLibCore/path_functions.py +215 -0
  21. OpenApiLibCore/path_invalidation.py +42 -0
  22. OpenApiLibCore/protocols.py +38 -0
  23. OpenApiLibCore/request_data.py +246 -0
  24. OpenApiLibCore/resource_relations.py +55 -0
  25. OpenApiLibCore/validation.py +380 -0
  26. OpenApiLibCore/value_utils.py +216 -481
  27. openapi_libgen/__init__.py +3 -0
  28. openapi_libgen/command_line.py +75 -0
  29. openapi_libgen/generator.py +82 -0
  30. openapi_libgen/parsing_utils.py +30 -0
  31. openapi_libgen/spec_parser.py +154 -0
  32. openapi_libgen/templates/__init__.jinja +3 -0
  33. openapi_libgen/templates/library.jinja +30 -0
  34. robotframework_openapitools-1.0.0.dist-info/METADATA +249 -0
  35. robotframework_openapitools-1.0.0.dist-info/RECORD +40 -0
  36. {robotframework_openapitools-0.3.0.dist-info → robotframework_openapitools-1.0.0.dist-info}/WHEEL +1 -1
  37. robotframework_openapitools-1.0.0.dist-info/entry_points.txt +3 -0
  38. roboswag/__init__.py +0 -9
  39. roboswag/__main__.py +0 -3
  40. roboswag/auth.py +0 -44
  41. roboswag/cli.py +0 -80
  42. roboswag/core.py +0 -85
  43. roboswag/generate/__init__.py +0 -1
  44. roboswag/generate/generate.py +0 -121
  45. roboswag/generate/models/__init__.py +0 -0
  46. roboswag/generate/models/api.py +0 -219
  47. roboswag/generate/models/definition.py +0 -28
  48. roboswag/generate/models/endpoint.py +0 -68
  49. roboswag/generate/models/parameter.py +0 -25
  50. roboswag/generate/models/response.py +0 -8
  51. roboswag/generate/models/tag.py +0 -16
  52. roboswag/generate/models/utils.py +0 -60
  53. roboswag/generate/templates/api_init.jinja +0 -15
  54. roboswag/generate/templates/models.jinja +0 -7
  55. roboswag/generate/templates/paths.jinja +0 -68
  56. roboswag/logger.py +0 -33
  57. roboswag/validate/__init__.py +0 -6
  58. roboswag/validate/core.py +0 -3
  59. roboswag/validate/schema.py +0 -21
  60. roboswag/validate/text_response.py +0 -14
  61. robotframework_openapitools-0.3.0.dist-info/METADATA +0 -41
  62. robotframework_openapitools-0.3.0.dist-info/RECORD +0 -41
  63. {robotframework_openapitools-0.3.0.dist-info → robotframework_openapitools-1.0.0.dist-info}/LICENSE +0 -0
@@ -1,311 +1,55 @@
1
- """
2
- # OpenApiDriver for Robot Framework®
3
-
4
- OpenApiDriver is an extension of the Robot Framework® DataDriver library that allows
5
- for generation and execution of test cases based on the information in an OpenAPI
6
- document (also known as Swagger document).
7
- This document explains how to use the OpenApiDriver library.
8
-
9
- For more information about Robot Framework®, see http://robotframework.org.
10
-
11
- For more information about the DataDriver library, see
12
- https://github.com/Snooz82/robotframework-datadriver.
13
-
14
- ---
15
-
16
- > Note: OpenApiDriver is still under development so there are currently
17
- restrictions / limitations that you may encounter when using this library to run
18
- tests against an API. See [Limitations](#limitations) for details.
19
-
20
- ---
21
-
22
- ## Installation
23
-
24
- If you already have Python >= 3.8 with pip installed, you can simply run:
25
-
26
- `pip install --upgrade robotframework-openapidriver`
27
-
28
- ---
29
-
30
- ## OpenAPI (aka Swagger)
31
-
32
- The OpenAPI Specification (OAS) defines a standard, language-agnostic interface
33
- to RESTful APIs, see https://swagger.io/specification/
34
-
35
- The OpenApiDriver module implements a reader class that generates a test case for
36
- each path, method and response (i.e. every response for each endpoint) that is defined
37
- in an OpenAPI document, typically an openapi.json or openapi.yaml file.
38
-
39
- > Note: OpenApiDriver is designed for APIs based on the OAS v3
40
- The library has not been tested for APIs based on the OAS v2.
41
-
42
- ---
43
-
44
- ## Getting started
45
-
46
- Before trying to use OpenApiDriver to run automatic validations on the target API
47
- it's recommended to first ensure that the openapi document for the API is valid
48
- under the OpenAPI Specification.
49
-
50
- This can be done using the command line interface of a package that is installed as
51
- a prerequisite for OpenApiDriver.
52
- Both a local openapi.json or openapi.yaml file or one hosted by the API server
53
- can be checked using the `prance validate <reference_to_file>` shell command:
54
-
55
- ```shell
56
- prance validate --backend=openapi-spec-validator http://localhost:8000/openapi.json
57
- Processing "http://localhost:8000/openapi.json"...
58
- -> Resolving external references.
59
- Validates OK as OpenAPI 3.0.2!
60
-
61
- prance validate --backend=openapi-spec-validator /tests/files/petstore_openapi.yaml
62
- Processing "/tests/files/petstore_openapi.yaml"...
63
- -> Resolving external references.
64
- Validates OK as OpenAPI 3.0.2!
65
- ```
66
-
67
- You'll have to change the url or file reference to the location of the openapi
68
- document for your API.
69
-
70
- > Note: Although recursion is technically allowed under the OAS, tool support is limited
71
- and changing the OAS to not use recursion is recommended.
72
- OpenApiDriver has limited support for parsing OpenAPI documents with
73
- recursion in them. See the `recursion_limit` and `recursion_default` parameters.
74
-
75
- If the openapi document passes this validation, the next step is trying to do a test
76
- run with a minimal test suite.
77
- The example below can be used, with `source` and `origin` altered to fit your situation.
78
-
79
- ``` robotframework
80
- *** Settings ***
81
- Library OpenApiDriver
82
- ... source=http://localhost:8000/openapi.json
83
- ... origin=http://localhost:8000
84
- Test Template Validate Using Test Endpoint Keyword
85
-
86
- *** Test Cases ***
87
- Test Endpoint for ${method} on ${path} where ${status_code} is expected
88
-
89
- *** Keywords ***
90
- Validate Using Test Endpoint Keyword
91
- [Arguments] ${path} ${method} ${status_code}
92
- Test Endpoint
93
- ... path=${path} method=${method} status_code=${status_code}
94
-
95
- ```
96
-
97
- Running the above suite for the first time is likely to result in some
98
- errors / failed tests.
99
- You should look at the Robot Framework `log.html` to determine the reasons
100
- for the failing tests.
101
- Depending on the reasons for the failures, different solutions are possible.
102
-
103
- Details about the OpenApiDriver library parameters that you may need can be found
104
- [here](https://marketsquare.github.io/robotframework-openapidriver/openapidriver.html).
105
-
106
- The OpenApiDriver also support handling of relations between resources within the scope
107
- of the API being validated as well as handling dependencies on resources outside the
108
- scope of the API. In addition there is support for handling restrictions on the values
109
- of parameters and properties.
110
-
111
- Details about the `mappings_path` variable usage can be found
112
- [here](https://marketsquare.github.io/robotframework-openapi-libcore/advanced_use.html).
113
-
114
- ---
115
-
116
- ## Limitations
117
-
118
- There are currently a number of limitations to supported API structures, supported
119
- data types and properties. The following list details the most important ones:
120
- - Only JSON request and response bodies are supported.
121
- - No support for per-path authorization levels (only simple 401 / 403 validation).
122
-
123
- """
124
-
1
+ from collections.abc import Mapping, MutableMapping
125
2
  from pathlib import Path
126
- from typing import Any, Dict, Iterable, List, Optional, Tuple, Union
3
+ from types import MappingProxyType
4
+ from typing import Iterable
127
5
 
128
- from DataDriver import DataDriver
6
+ from DataDriver.DataDriver import DataDriver
129
7
  from requests.auth import AuthBase
130
8
  from requests.cookies import RequestsCookieJar as CookieJar
131
9
  from robot.api.deco import library
132
10
 
133
- from OpenApiDriver.openapi_executors import OpenApiExecutors, ValidationLevel
11
+ from OpenApiDriver.openapi_executors import OpenApiExecutors
134
12
  from OpenApiDriver.openapi_reader import OpenApiReader
13
+ from OpenApiLibCore import ValidationLevel
14
+ from OpenApiLibCore.annotations import JSON
15
+ from openapitools_docs.docstrings import (
16
+ OPENAPIDRIVER_INIT_DOCSTRING,
17
+ OPENAPIDRIVER_LIBRARY_DOCSTRING,
18
+ )
135
19
 
20
+ default_str_mapping: Mapping[str, str] = MappingProxyType({})
136
21
 
137
- @library(scope="SUITE", doc_format="ROBOT")
138
- class OpenApiDriver(OpenApiExecutors, DataDriver):
139
- """
140
- Visit the [https://github.com/MarketSquare/robotframework-openapidriver | library page]
141
- for an introduction and examples.
142
- """
143
22
 
144
- def __init__( # pylint: disable=too-many-arguments, too-many-locals, dangerous-default-value
23
+ @library(scope="SUITE", doc_format="HTML")
24
+ class OpenApiDriver(OpenApiExecutors, DataDriver):
25
+ def __init__( # noqa: PLR0913, pylint: disable=dangerous-default-value
145
26
  self,
146
27
  source: str,
147
28
  origin: str = "",
148
29
  base_path: str = "",
149
- included_paths: Optional[Iterable[str]] = None,
150
- ignored_paths: Optional[Iterable[str]] = None,
151
- ignored_responses: Optional[Iterable[int]] = None,
152
- ignored_testcases: Optional[Iterable[Tuple[str, str, int]]] = None,
30
+ included_paths: Iterable[str] = frozenset(),
31
+ ignored_paths: Iterable[str] = frozenset(),
32
+ ignored_responses: Iterable[int] = frozenset(),
33
+ ignored_testcases: Iterable[tuple[str, str, int]] = frozenset(),
153
34
  response_validation: ValidationLevel = ValidationLevel.WARN,
154
35
  disable_server_validation: bool = True,
155
- mappings_path: Union[str, Path] = "",
36
+ mappings_path: str | Path = "",
156
37
  invalid_property_default_response: int = 422,
157
38
  default_id_property_name: str = "id",
158
- faker_locale: Optional[Union[str, List[str]]] = None,
39
+ faker_locale: str | list[str] = "",
159
40
  require_body_for_invalid_url: bool = False,
160
41
  recursion_limit: int = 1,
161
- recursion_default: Any = {},
42
+ recursion_default: JSON = {},
162
43
  username: str = "",
163
44
  password: str = "",
164
45
  security_token: str = "",
165
- auth: Optional[AuthBase] = None,
166
- cert: Optional[Union[str, Tuple[str, str]]] = None,
167
- verify_tls: Optional[Union[bool, str]] = True,
168
- extra_headers: Optional[Dict[str, str]] = None,
169
- cookies: Optional[Union[Dict[str, str], CookieJar]] = None,
170
- proxies: Optional[Dict[str, str]] = None,
171
- ):
172
- """
173
- == Base parameters ==
174
-
175
- === source ===
176
- An absolute path to an openapi.json or openapi.yaml file or an url to such a file.
177
-
178
- === origin ===
179
- The server (and port) of the target server. E.g. ``https://localhost:8000``
180
-
181
- === base_path ===
182
- The routing between ``origin`` and the endpoints as found in the ``paths``
183
- section in the openapi document.
184
- E.g. ``/petshop/v2``.
185
-
186
- == Test case generation and execution ==
187
-
188
- === included_paths ===
189
- A list of paths that will be included when generating the test cases.
190
- The ``*`` character can be used at the end of a partial path to include all paths
191
- starting with the partial path (wildcard include).
192
-
193
- === ignored_paths ===
194
- A list of paths that will be ignored when generating the test cases.
195
- The ``*`` character can be used at the end of a partial path to ignore all paths
196
- starting with the partial path (wildcard ignore).
197
-
198
- === ignored_responses ===
199
- A list of responses that will be ignored when generating the test cases.
200
-
201
- === ignored_testcases ===
202
- A list of specific test cases that, if it would be generated, will be ignored.
203
- Specific test cases to ignore must be specified as a ``Tuple`` or ``List``
204
- of ``path``, ``method`` and ``response``.
205
-
206
- === response_validation ===
207
- By default, a ``WARN`` is logged when the Response received after a Request does not
208
- comply with the schema as defined in the openapi document for the given operation. The
209
- following values are supported:
210
-
211
- - ``DISABLED``: All Response validation errors will be ignored
212
- - ``INFO``: Any Response validation erros will be logged at ``INFO`` level
213
- - ``WARN``: Any Response validation erros will be logged at ``WARN`` level
214
- - ``STRICT``: The Test Case will fail on any Response validation errors
215
-
216
- === disable_server_validation ===
217
- If enabled by setting this parameter to ``True``, the Response validation will also
218
- include possible errors for Requests made to a server address that is not defined in
219
- the list of servers in the openapi document. This generally means that if there is a
220
- mismatch, every Test Case will raise this error. Note that ``localhost`` and
221
- ``127.0.0.1`` are not considered the same by Response validation.
222
-
223
- == API-specific configurations ==
224
-
225
- === mappings_path ===
226
- See [https://marketsquare.github.io/robotframework-openapi-libcore/advanced_use.html | this page]
227
- for an in-depth explanation.
228
-
229
- === invalid_property_default_response ===
230
- The default response code for requests with a JSON body that does not comply
231
- with the schema.
232
- Example: a value outside the specified range or a string value
233
- for a property defined as integer in the schema.
234
-
235
- === default_id_property_name ===
236
- The default name for the property that identifies a resource (i.e. a unique
237
- entity) within the API.
238
- The default value for this property name is ``id``.
239
- If the target API uses a different name for all the resources within the API,
240
- you can configure it globally using this property.
241
-
242
- If different property names are used for the unique identifier for different
243
- types of resources, an ``ID_MAPPING`` can be implemented using the ``mappings_path``.
244
-
245
- === faker_locale ===
246
- A locale string or list of locale strings to pass to the Faker library to be
247
- used in generation of string data for supported format types.
248
-
249
- === require_body_for_invalid_url ===
250
- When a request is made against an invalid url, this usually is because of a "404" request;
251
- a request for a resource that does not exist. Depending on API implementation, when a
252
- request with a missing or invalid request body is made on a non-existent resource,
253
- either a 404 or a 422 or 400 Response is normally returned. If the API being tested
254
- processes the request body before checking if the requested resource exists, set
255
- this parameter to True.
256
-
257
- == Parsing parameters ==
258
-
259
- === recursion_limit ===
260
- The recursion depth to which to fully parse recursive references before the
261
- `recursion_default` is used to end the recursion.
262
-
263
- === recursion_default ===
264
- The value that is used instead of the referenced schema when the
265
- `recursion_limit` has been reached.
266
- The default `{}` represents an empty object in JSON.
267
- Depending on schema definitions, this may cause schema validation errors.
268
- If this is the case, 'None' (``${NONE}`` in Robot Framework) or an empty list
269
- can be tried as an alternative.
270
-
271
- == Security-related parameters ==
272
- _Note: these parameters are equivalent to those in the ``requests`` library._
273
-
274
- === username ===
275
- The username to be used for Basic Authentication.
276
-
277
- === password ===
278
- The password to be used for Basic Authentication.
279
-
280
- === security_token ===
281
- The token to be used for token based security using the ``Authorization`` header.
282
-
283
- === auth ===
284
- A [https://requests.readthedocs.io/en/latest/api/#authentication | requests ``AuthBase`` instance]
285
- to be used for authentication instead of the ``username`` and ``password``.
286
-
287
- === cert ===
288
- The SSL certificate to use with all requests.
289
- If string: the path to ssl client cert file (.pem).
290
- If tuple: the ('cert', 'key') pair.
291
-
292
- === verify_tls ===
293
- Whether or not to verify the TLS / SSL certificate of the server.
294
- If boolean: whether or not to verify the server TLS certificate.
295
- If string: path to a CA bundle to use for verification.
296
-
297
- === extra_headers ===
298
- A dictionary with extra / custom headers that will be send with every request.
299
- This parameter can be used to send headers that are not documented in the
300
- openapi document or to provide an API-key.
301
-
302
- === cookies ===
303
- A dictionary or [https://docs.python.org/3/library/http.cookiejar.html#http.cookiejar.CookieJar | CookieJar object]
304
- to send with all requests.
305
-
306
- === proxies ===
307
- A dictionary of 'protocol': 'proxy url' to use for all requests.
308
- """
46
+ auth: AuthBase | None = None,
47
+ cert: str | tuple[str, str] = "",
48
+ verify_tls: bool | str = True,
49
+ extra_headers: Mapping[str, str] = default_str_mapping,
50
+ cookies: MutableMapping[str, str] | CookieJar | None = None,
51
+ proxies: MutableMapping[str, str] | None = None,
52
+ ) -> None:
309
53
  included_paths = included_paths if included_paths else ()
310
54
  ignored_paths = ignored_paths if ignored_paths else ()
311
55
  ignored_responses = ignored_responses if ignored_responses else ()
@@ -348,16 +92,7 @@ class OpenApiDriver(OpenApiExecutors, DataDriver):
348
92
  ignored_testcases=ignored_testcases,
349
93
  )
350
94
 
95
+ __init__.__doc__ = OPENAPIDRIVER_INIT_DOCSTRING
351
96
 
352
- class DocumentationGenerator(OpenApiDriver):
353
- __doc__ = OpenApiDriver.__doc__
354
97
 
355
- @staticmethod
356
- def get_keyword_names() -> List[str]:
357
- """Curated keywords for libdoc and libspec."""
358
- return [
359
- "test_unauthorized",
360
- "test_forbidden",
361
- "test_invalid_url",
362
- "test_endpoint",
363
- ] # pragma: no cover
98
+ OpenApiDriver.__doc__ = OPENAPIDRIVER_LIBRARY_DOCSTRING
@@ -1,3 +1,4 @@
1
+ # pylint: disable=invalid-name
1
2
  """
2
3
  The OpenApiLibCore package is intended to be used as a dependency for other
3
4
  Robot Framework libraries that facilitate the testing of OpenAPI / Swagger APIs.
@@ -18,37 +19,62 @@ from OpenApiLibCore.dto_base import (
18
19
  IdReference,
19
20
  PathPropertiesConstraint,
20
21
  PropertyValueConstraint,
21
- Relation,
22
+ ResourceRelation,
22
23
  UniquePropertyValueConstraint,
23
- resolve_schema,
24
24
  )
25
25
  from OpenApiLibCore.dto_utils import DefaultDto
26
26
  from OpenApiLibCore.openapi_libcore import (
27
27
  OpenApiLibCore,
28
- RequestData,
29
- RequestValues,
30
- ValidationLevel,
31
28
  )
32
- from OpenApiLibCore.value_utils import IGNORE
29
+ from OpenApiLibCore.request_data import RequestData, RequestValues
30
+ from OpenApiLibCore.validation import ValidationLevel
31
+ from OpenApiLibCore.value_utils import IGNORE, UNSET
33
32
 
34
33
  try:
35
34
  __version__ = version("robotframework-openapi-libcore")
36
- except Exception: # pragma: no cover
35
+ except Exception: # pragma: no cover pylint: disable=broad-exception-caught
37
36
  pass
38
37
 
38
+
39
+ KEYWORD_NAMES = [
40
+ "set_origin",
41
+ "set_security_token",
42
+ "set_basic_auth",
43
+ "set_auth",
44
+ "set_extra_headers",
45
+ "get_request_values",
46
+ "get_request_data",
47
+ "get_invalid_body_data",
48
+ "get_invalidated_parameters",
49
+ "get_json_data_with_conflict",
50
+ "get_valid_url",
51
+ "get_valid_id_for_path",
52
+ "get_parameterized_path_from_url",
53
+ "get_ids_from_url",
54
+ "get_invalidated_url",
55
+ "ensure_in_use",
56
+ "authorized_request",
57
+ "perform_validated_request",
58
+ "validate_response_using_validator",
59
+ "assert_href_to_resource_is_valid",
60
+ "validate_response",
61
+ "validate_send_response",
62
+ ]
63
+
64
+
39
65
  __all__ = [
66
+ "IGNORE",
67
+ "UNSET",
68
+ "DefaultDto",
40
69
  "Dto",
41
70
  "IdDependency",
42
71
  "IdReference",
72
+ "OpenApiLibCore",
43
73
  "PathPropertiesConstraint",
44
74
  "PropertyValueConstraint",
45
- "Relation",
46
- "UniquePropertyValueConstraint",
47
- "DefaultDto",
48
- "OpenApiLibCore",
49
75
  "RequestData",
50
76
  "RequestValues",
77
+ "ResourceRelation",
78
+ "UniquePropertyValueConstraint",
51
79
  "ValidationLevel",
52
- "resolve_schema",
53
- "IGNORE",
54
80
  ]
@@ -0,0 +1,10 @@
1
+ """Module holding reusable compound annotations."""
2
+
3
+ from typing import Union
4
+
5
+ from typing_extensions import TypeAliasType
6
+
7
+ JSON = TypeAliasType(
8
+ "JSON",
9
+ "Union[dict[str, JSON], list[JSON], str, bytes, int, float, bool, None]",
10
+ )
@@ -0,0 +1,10 @@
1
+ """
2
+ Module holding the functions related to data generation
3
+ for the requests made as part of keyword exection.
4
+ """
5
+
6
+ from .data_generation_core import get_request_data
7
+
8
+ __all__ = [
9
+ "get_request_data",
10
+ ]