robotframework-schemathesislibrary 0.52.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.

Potentially problematic release.


This version of robotframework-schemathesislibrary might be problematic. Click here for more details.

@@ -11,69 +11,25 @@
11
11
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
- from dataclasses import dataclass
15
- from pathlib import Path
16
- from typing import Any
14
+ from typing import TYPE_CHECKING, Any
17
15
 
18
16
  from DataDriver import DataDriver # type: ignore
19
- from DataDriver.AbstractReaderClass import AbstractReaderClass # type: ignore
20
- from DataDriver.ReaderConfig import TestCaseData # type: ignore
21
- from hypothesis import HealthCheck, Phase, Verbosity, given, settings
22
- from hypothesis import strategies as st
23
17
  from robot.api import logger
24
18
  from robot.api.deco import keyword
25
19
  from robot.result.model import TestCase as ResultTestCase # type: ignore
26
20
  from robot.result.model import TestSuite as ResultTestSuite # type: ignore
27
21
  from robot.running.model import TestCase, TestSuite # type: ignore
28
22
  from robotlibcore import DynamicCore # type: ignore
29
- from schemathesis import Case, openapi
23
+ from schemathesis import Case
30
24
  from schemathesis.core import NotSet
31
- from schemathesis.core.result import Ok
32
25
  from schemathesis.core.transport import Response
33
26
 
34
- __version__ = "0.52.0"
35
-
36
-
37
- @dataclass
38
- class Options:
39
- max_examples: int
40
- headers: dict[str, Any] | None = None
41
- path: "Path|None" = None
42
- url: "str|None" = None
43
-
44
-
45
- class SchemathesisReader(AbstractReaderClass):
46
- options: "Options|None" = None
47
-
48
- def get_data_from_source(self) -> list[TestCaseData]:
49
- if not self.options:
50
- raise ValueError("Options must be set before calling get_data_from_source.")
51
- url = self.options.url
52
- path = self.options.path
53
- if path and not Path(path).is_file():
54
- raise ValueError(f"Provided path '{path}' is not a valid file.")
55
- if path:
56
- schema = openapi.from_path(path)
57
- elif url:
58
- headers = self.options.headers or {}
59
- schema = openapi.from_url(url, headers=headers)
60
- else:
61
- raise ValueError("Either 'url' or 'path' must be provided to SchemathesisLibrary.")
62
- all_cases: list[TestCaseData] = []
63
- for op in schema.get_all_operations():
64
- if isinstance(op, Ok):
65
- # NOTE: (dd): `as_strategy` also accepts GenerationMode
66
- # It could be used to produce positive / negative tests
67
- strategy = op.ok().as_strategy().map(from_case) # type: ignore
68
- add_examples(strategy, all_cases, self.options.max_examples) # type: ignore
69
- return all_cases
70
-
71
-
72
- def from_case(case: Case) -> TestCaseData:
73
- return TestCaseData(
74
- test_case_name=f"{case.operation.label} - {case.id}",
75
- arguments={"${case}": case},
76
- )
27
+ from .schemathesisreader import Options, SchemathesisReader
28
+
29
+ if TYPE_CHECKING:
30
+ from pathlib import Path
31
+
32
+ __version__ = "1.0.0"
77
33
 
78
34
 
79
35
  class SchemathesisLibrary(DynamicCore):
@@ -121,17 +77,21 @@ class SchemathesisLibrary(DynamicCore):
121
77
  max_examples: int = 5,
122
78
  path: "Path|None" = None,
123
79
  url: "str|None" = None,
80
+ auth: str | None = None,
124
81
  ) -> None:
125
82
  """The SchemathesisLibrary can be initialized with the following arguments:
126
83
 
127
84
  | =Argument= | =Description= |
128
- | `headers` | Optional HTTP headers to be used schema is downloaded from `url`. |
85
+ | `headers` | Optional HTTP headers to be used when schema is downloaded from `url`. |
129
86
  | `max_examples` | Maximum number of examples to generate for each operation. Default is 5. |
130
87
  | `path` | Path to the OpenAPI schema file. Using either `path` or `url` is mandatory. |
131
88
  | `url` | URL where the OpenAPI schema can be downloaded. |
89
+ | `auth` | Optional authentication class to be used passed for Schemathesis authentication when test cases are executed. |
132
90
  """
133
91
  self.ROBOT_LIBRARY_LISTENER = self
134
- SchemathesisReader.options = Options(headers=headers, max_examples=max_examples, path=path, url=url)
92
+ SchemathesisReader.options = Options(
93
+ headers=headers, max_examples=max_examples, path=path, url=url, auth=auth
94
+ )
135
95
  self.data_driver = DataDriver(reader_class=SchemathesisReader)
136
96
  DynamicCore.__init__(self, [])
137
97
 
@@ -146,9 +106,8 @@ class SchemathesisLibrary(DynamicCore):
146
106
  self,
147
107
  case: Case,
148
108
  *,
149
- auth: "Any|None" = None,
150
- base_url: "str|None" = None,
151
- headers: "dict[str, Any]|None" = None,
109
+ base_url: str | None = None,
110
+ headers: dict[str, Any] | None = None,
152
111
  ) -> Response:
153
112
  """Call and validate a Schemathesis case.
154
113
 
@@ -157,7 +116,7 @@ class SchemathesisLibrary(DynamicCore):
157
116
  """
158
117
  self.info(f"Case: {case.path} | {case.method} | {case.path_parameters}")
159
118
  self._log_case(case, headers)
160
- response = case.call_and_validate(base_url=base_url, headers=headers, auth=auth)
119
+ response = case.call_and_validate(base_url=base_url, headers=headers)
161
120
  self._log_request(response)
162
121
  self.debug(f"Response: {response.headers} | {response.status_code} | {response.text}")
163
122
  return response
@@ -167,9 +126,8 @@ class SchemathesisLibrary(DynamicCore):
167
126
  self,
168
127
  case: Case,
169
128
  *,
170
- auth: "Any|None" = None,
171
- base_url: "str|None" = None,
172
- headers: "dict[str, Any]|None" = None,
129
+ base_url: str | None = None,
130
+ headers: dict[str, Any] | None = None,
173
131
  ) -> Response:
174
132
  """Call a Schemathesis case without validation.
175
133
 
@@ -182,7 +140,7 @@ class SchemathesisLibrary(DynamicCore):
182
140
  """
183
141
  self.info(f"Calling case: {case.path} | {case.method} | {case.path_parameters}")
184
142
  self._log_case(case)
185
- response = case.call(base_url=base_url, headers=headers, auth=auth)
143
+ response = case.call(base_url=base_url, headers=headers)
186
144
  self._log_request(response)
187
145
  return response
188
146
 
@@ -222,19 +180,3 @@ class SchemathesisLibrary(DynamicCore):
222
180
  f"Request: {resposen.request.method} {resposen.request.url} "
223
181
  f"headers: {resposen.request.headers!r} body: {resposen.request.body!r}"
224
182
  )
225
-
226
-
227
- def add_examples(strategy: st.SearchStrategy, container: list[TestCaseData], max_examples: int) -> None:
228
- @given(strategy)
229
- @settings(
230
- database=None,
231
- max_examples=max_examples,
232
- deadline=None,
233
- verbosity=Verbosity.quiet,
234
- phases=(Phase.generate,),
235
- suppress_health_check=list(HealthCheck),
236
- )
237
- def example_generating_inner_function(ex: Any) -> None:
238
- container.append(ex)
239
-
240
- example_generating_inner_function()
@@ -0,0 +1,96 @@
1
+ # Copyright 2025- Tatu Aalto
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ from dataclasses import dataclass
15
+ from pathlib import Path
16
+ from typing import Any
17
+
18
+ from DataDriver.AbstractReaderClass import AbstractReaderClass # type: ignore
19
+ from DataDriver.ReaderConfig import TestCaseData # type: ignore
20
+ from hypothesis import HealthCheck, Phase, Verbosity, given, settings
21
+ from hypothesis import strategies as st
22
+ from robot.api import logger
23
+ from robot.utils.importer import Importer # type: ignore
24
+ from schemathesis import Case, openapi
25
+ from schemathesis.core.result import Ok
26
+
27
+
28
+ @dataclass
29
+ class Options:
30
+ max_examples: int
31
+ headers: dict[str, Any] | None = None
32
+ path: "Path|None" = None
33
+ url: str | None = None
34
+ auth: str | None = None
35
+
36
+
37
+ class SchemathesisReader(AbstractReaderClass):
38
+ options: "Options|None" = None
39
+
40
+ def get_data_from_source(self) -> list[TestCaseData]:
41
+ if not self.options:
42
+ raise ValueError("Options must be set before calling get_data_from_source.")
43
+ url = self.options.url
44
+ path = self.options.path
45
+ if path and not Path(path).is_file():
46
+ raise ValueError(f"Provided path '{path}' is not a valid file.")
47
+ if path:
48
+ schema = openapi.from_path(path)
49
+ elif url:
50
+ headers = self.options.headers or {}
51
+ schema = openapi.from_url(url, headers=headers)
52
+ else:
53
+ raise ValueError("Either 'url' or 'path' must be provided to SchemathesisLibrary.")
54
+ all_cases: list[TestCaseData] = []
55
+ if self.options.auth:
56
+ import_extensions(self.options.auth)
57
+ logger.info(f"Using auth extension from: {self.options.auth}")
58
+
59
+ for op in schema.get_all_operations():
60
+ if isinstance(op, Ok):
61
+ # NOTE: (dd): `as_strategy` also accepts GenerationMode
62
+ # It could be used to produce positive / negative tests
63
+ strategy = op.ok().as_strategy().map(from_case) # type: ignore
64
+ add_examples(strategy, all_cases, self.options.max_examples) # type: ignore
65
+ return all_cases
66
+
67
+
68
+ def from_case(case: Case) -> TestCaseData:
69
+ return TestCaseData(
70
+ test_case_name=f"{case.operation.label} - {case.id}",
71
+ arguments={"${case}": case},
72
+ )
73
+
74
+
75
+ def add_examples(strategy: st.SearchStrategy, container: list[TestCaseData], max_examples: int) -> None:
76
+ @given(strategy)
77
+ @settings(
78
+ database=None,
79
+ max_examples=max_examples,
80
+ deadline=None,
81
+ verbosity=Verbosity.quiet,
82
+ phases=(Phase.generate,),
83
+ suppress_health_check=list(HealthCheck),
84
+ )
85
+ def example_generating_inner_function(ex: Any) -> None:
86
+ container.append(ex)
87
+
88
+ example_generating_inner_function()
89
+
90
+
91
+ def import_extensions(library: str | Path) -> Any:
92
+ """Import any extensions for SchemathesisLibrary."""
93
+ importer = Importer("test library")
94
+ lib = importer.import_module(library)
95
+ logger.info(f"Imported extension module: {lib}")
96
+ return lib
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: robotframework-schemathesislibrary
3
- Version: 0.52.0
3
+ Version: 1.0.0
4
4
  Summary: Robot Framework SchemathesisLibrary to automatically create test cases from API specifications.
5
5
  Author-email: Tatu Aalto <aalto.tatu@gmail.com>
6
6
  License-Expression: Apache-2.0
@@ -0,0 +1,7 @@
1
+ SchemathesisLibrary/__init__.py,sha256=eAlV97tkZtcC4pC1XYj_z6YLjfYXX4zTiOUeweHu51Y,6991
2
+ SchemathesisLibrary/schemathesisreader.py,sha256=MmA0ZEtIDjIGwKUZKTyNoqYaA0Euuj7G9I_zcaKulv4,3552
3
+ robotframework_schemathesislibrary-1.0.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
4
+ robotframework_schemathesislibrary-1.0.0.dist-info/METADATA,sha256=j2nf_5CkRQYP5S_OR6Hscs1wz_Yg-QCqMXZPHbP8rTU,2669
5
+ robotframework_schemathesislibrary-1.0.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
6
+ robotframework_schemathesislibrary-1.0.0.dist-info/top_level.txt,sha256=bVGNag3IIuKRUVgjTtfRyDvyN3qRFYSSpmbCl5MBrUU,20
7
+ robotframework_schemathesislibrary-1.0.0.dist-info/RECORD,,
@@ -1,6 +0,0 @@
1
- SchemathesisLibrary/__init__.py,sha256=sqLT4IpfGJ2vzqqYnXwcgXnVeQCy3JPNaERr_w9ZsmE,9116
2
- robotframework_schemathesislibrary-0.52.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
3
- robotframework_schemathesislibrary-0.52.0.dist-info/METADATA,sha256=8uVqXiG-GCaIzdJrl_8sSgyTLgN_-SMfLd1S_oWBCzc,2670
4
- robotframework_schemathesislibrary-0.52.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
5
- robotframework_schemathesislibrary-0.52.0.dist-info/top_level.txt,sha256=bVGNag3IIuKRUVgjTtfRyDvyN3qRFYSSpmbCl5MBrUU,20
6
- robotframework_schemathesislibrary-0.52.0.dist-info/RECORD,,