schemathesis 3.39.1__py3-none-any.whl → 3.39.3__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.
- schemathesis/_hypothesis.py +14 -9
- schemathesis/cli/junitxml.py +15 -7
- schemathesis/models.py +1 -0
- schemathesis/specs/openapi/checks.py +1 -1
- schemathesis/specs/openapi/schemas.py +5 -6
- {schemathesis-3.39.1.dist-info → schemathesis-3.39.3.dist-info}/METADATA +2 -2
- {schemathesis-3.39.1.dist-info → schemathesis-3.39.3.dist-info}/RECORD +10 -10
- {schemathesis-3.39.1.dist-info → schemathesis-3.39.3.dist-info}/WHEEL +0 -0
- {schemathesis-3.39.1.dist-info → schemathesis-3.39.3.dist-info}/entry_points.txt +0 -0
- {schemathesis-3.39.1.dist-info → schemathesis-3.39.3.dist-info}/licenses/LICENSE +0 -0
schemathesis/_hypothesis.py
CHANGED
|
@@ -199,21 +199,26 @@ def add_examples(
|
|
|
199
199
|
if invalid_headers:
|
|
200
200
|
add_invalid_example_header_mark(original_test, invalid_headers)
|
|
201
201
|
continue
|
|
202
|
-
|
|
203
|
-
try:
|
|
204
|
-
media_type = parse_content_type(example.media_type)
|
|
205
|
-
if media_type == ("application", "x-www-form-urlencoded"):
|
|
206
|
-
example.body = prepare_urlencoded(example.body)
|
|
207
|
-
except ValueError:
|
|
208
|
-
pass
|
|
202
|
+
adjust_urlencoded_payload(example)
|
|
209
203
|
test = hypothesis.example(case=example)(test)
|
|
210
204
|
return test
|
|
211
205
|
|
|
212
206
|
|
|
207
|
+
def adjust_urlencoded_payload(case: Case) -> None:
|
|
208
|
+
if case.media_type is not None:
|
|
209
|
+
try:
|
|
210
|
+
media_type = parse_content_type(case.media_type)
|
|
211
|
+
if media_type == ("application", "x-www-form-urlencoded"):
|
|
212
|
+
case.body = prepare_urlencoded(case.body)
|
|
213
|
+
except ValueError:
|
|
214
|
+
pass
|
|
215
|
+
|
|
216
|
+
|
|
213
217
|
def add_coverage(
|
|
214
218
|
test: Callable, operation: APIOperation, data_generation_methods: list[DataGenerationMethod]
|
|
215
219
|
) -> Callable:
|
|
216
220
|
for example in _iter_coverage_cases(operation, data_generation_methods):
|
|
221
|
+
adjust_urlencoded_payload(example)
|
|
217
222
|
test = hypothesis.example(case=example)(test)
|
|
218
223
|
return test
|
|
219
224
|
|
|
@@ -322,7 +327,7 @@ def _iter_coverage_cases(
|
|
|
322
327
|
case = operation.make_case(**template)
|
|
323
328
|
case._explicit_method = method
|
|
324
329
|
case.data_generation_method = DataGenerationMethod.negative
|
|
325
|
-
case.meta = _make_meta(description=f"Unspecified HTTP method: {method}")
|
|
330
|
+
case.meta = _make_meta(description=f"Unspecified HTTP method: {method.upper()}")
|
|
326
331
|
yield case
|
|
327
332
|
# Generate duplicate query parameters
|
|
328
333
|
if operation.query:
|
|
@@ -518,7 +523,7 @@ def prepare_urlencoded(data: Any) -> Any:
|
|
|
518
523
|
for key, value in item.items():
|
|
519
524
|
output.append((key, value))
|
|
520
525
|
else:
|
|
521
|
-
output.append(item)
|
|
526
|
+
output.append((item, "arbitrary-value"))
|
|
522
527
|
return output
|
|
523
528
|
return data
|
|
524
529
|
|
schemathesis/cli/junitxml.py
CHANGED
|
@@ -24,7 +24,7 @@ if TYPE_CHECKING:
|
|
|
24
24
|
@dataclass
|
|
25
25
|
class JunitXMLHandler(EventHandler):
|
|
26
26
|
file_handle: LazyFile
|
|
27
|
-
test_cases:
|
|
27
|
+
test_cases: dict = field(default_factory=dict)
|
|
28
28
|
|
|
29
29
|
def handle_event(self, context: ExecutionContext, event: events.ExecutionEvent) -> None:
|
|
30
30
|
if isinstance(event, (events.AfterExecution, events.AfterStatefulExecution)):
|
|
@@ -33,23 +33,31 @@ class JunitXMLHandler(EventHandler):
|
|
|
33
33
|
name = f"{event_.result.method} {event_.result.path}"
|
|
34
34
|
else:
|
|
35
35
|
name = event_.result.verbose_name
|
|
36
|
-
|
|
36
|
+
if name in self.test_cases:
|
|
37
|
+
test_case = self.test_cases[name]
|
|
38
|
+
test_case.elapsed_sec += event_.elapsed_time
|
|
39
|
+
else:
|
|
40
|
+
test_case = TestCase(name, elapsed_sec=event_.elapsed_time, allow_multiple_subelements=True)
|
|
37
41
|
if event_.status == Status.failure:
|
|
38
42
|
_add_failure(test_case, event_.result.checks, context)
|
|
39
43
|
elif event_.status == Status.error:
|
|
40
|
-
test_case.add_error_info(
|
|
44
|
+
test_case.add_error_info(output=build_error_message(context, event_.result.errors[-1]))
|
|
41
45
|
elif event_.status == Status.skip:
|
|
42
|
-
test_case.add_skipped_info(
|
|
43
|
-
self.test_cases
|
|
46
|
+
test_case.add_skipped_info(output=event_.result.skip_reason)
|
|
47
|
+
self.test_cases[name] = test_case
|
|
44
48
|
elif isinstance(event, events.Finished):
|
|
45
|
-
test_suites = [
|
|
49
|
+
test_suites = [
|
|
50
|
+
TestSuite("schemathesis", test_cases=list(self.test_cases.values()), hostname=platform.node())
|
|
51
|
+
]
|
|
46
52
|
to_xml_report_file(file_descriptor=self.file_handle, test_suites=test_suites, prettyprint=True)
|
|
47
53
|
|
|
48
54
|
|
|
49
55
|
def _add_failure(test_case: TestCase, checks: list[SerializedCheck], context: ExecutionContext) -> None:
|
|
56
|
+
messages = []
|
|
50
57
|
for idx, (code_sample, group) in enumerate(group_by_case(checks, context.code_sample_style), 1):
|
|
51
58
|
checks = sorted(group, key=lambda c: c.name != "not_a_server_error")
|
|
52
|
-
|
|
59
|
+
messages.append(build_failure_message(context, idx, code_sample, checks))
|
|
60
|
+
test_case.add_failure_info(message="\n\n".join(messages))
|
|
53
61
|
|
|
54
62
|
|
|
55
63
|
def build_failure_message(context: ExecutionContext, idx: int, code_sample: str, checks: list[SerializedCheck]) -> str:
|
schemathesis/models.py
CHANGED
|
@@ -317,7 +317,7 @@ def use_after_free(ctx: CheckContext, response: GenericResponse, original: Case)
|
|
|
317
317
|
|
|
318
318
|
if not isinstance(original.operation.schema, BaseOpenAPISchema):
|
|
319
319
|
return True
|
|
320
|
-
if response.status_code == 404 or not original.source:
|
|
320
|
+
if response.status_code == 404 or not original.source or response.status_code >= 500:
|
|
321
321
|
return None
|
|
322
322
|
response = original.source.response
|
|
323
323
|
case = original.source.case
|
|
@@ -160,6 +160,9 @@ class BaseOpenAPISchema(BaseSchema):
|
|
|
160
160
|
) -> bool:
|
|
161
161
|
if method not in HTTP_METHODS:
|
|
162
162
|
return True
|
|
163
|
+
if self.filter_set.is_empty():
|
|
164
|
+
return False
|
|
165
|
+
path = self.get_full_path(path)
|
|
163
166
|
# Attribute assignment is way faster than creating a new namespace every time
|
|
164
167
|
operation = _ctx_cache.operation
|
|
165
168
|
operation.method = method
|
|
@@ -175,17 +178,15 @@ class BaseOpenAPISchema(BaseSchema):
|
|
|
175
178
|
paths = self.raw_schema["paths"]
|
|
176
179
|
except KeyError:
|
|
177
180
|
return
|
|
178
|
-
get_full_path = self.get_full_path
|
|
179
181
|
resolve = self.resolver.resolve
|
|
180
182
|
should_skip = self._should_skip
|
|
181
183
|
for path, path_item in paths.items():
|
|
182
|
-
full_path = get_full_path(path)
|
|
183
184
|
try:
|
|
184
185
|
if "$ref" in path_item:
|
|
185
186
|
_, path_item = resolve(path_item["$ref"])
|
|
186
187
|
# Straightforward iteration is faster than converting to a set & calculating length.
|
|
187
188
|
for method, definition in path_item.items():
|
|
188
|
-
if should_skip(
|
|
189
|
+
if should_skip(path, method, definition):
|
|
189
190
|
continue
|
|
190
191
|
yield definition
|
|
191
192
|
except SCHEMA_PARSING_ERRORS:
|
|
@@ -282,7 +283,6 @@ class BaseOpenAPISchema(BaseSchema):
|
|
|
282
283
|
|
|
283
284
|
context = HookContext()
|
|
284
285
|
# Optimization: local variables are faster than attribute access
|
|
285
|
-
get_full_path = self.get_full_path
|
|
286
286
|
dispatch_hook = self.dispatch_hook
|
|
287
287
|
resolve_path_item = self._resolve_path_item
|
|
288
288
|
resolve_shared_parameters = self._resolve_shared_parameters
|
|
@@ -294,7 +294,6 @@ class BaseOpenAPISchema(BaseSchema):
|
|
|
294
294
|
for path, path_item in paths.items():
|
|
295
295
|
method = None
|
|
296
296
|
try:
|
|
297
|
-
full_path = get_full_path(path) # Should be available for later use
|
|
298
297
|
dispatch_hook("before_process_path", context, path, path_item)
|
|
299
298
|
scope, path_item = resolve_path_item(path_item)
|
|
300
299
|
with in_scope(self.resolver, scope):
|
|
@@ -304,7 +303,7 @@ class BaseOpenAPISchema(BaseSchema):
|
|
|
304
303
|
continue
|
|
305
304
|
try:
|
|
306
305
|
resolved = resolve_operation(entry)
|
|
307
|
-
if should_skip(
|
|
306
|
+
if should_skip(path, method, resolved):
|
|
308
307
|
continue
|
|
309
308
|
parameters = resolved.get("parameters", ())
|
|
310
309
|
parameters = collect_parameters(itertools.chain(parameters, shared_parameters), resolved)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: schemathesis
|
|
3
|
-
Version: 3.39.
|
|
3
|
+
Version: 3.39.3
|
|
4
4
|
Summary: Property-based testing framework for Open API and GraphQL based apps
|
|
5
5
|
Project-URL: Documentation, https://schemathesis.readthedocs.io/en/stable/
|
|
6
6
|
Project-URL: Changelog, https://schemathesis.readthedocs.io/en/stable/changelog.html
|
|
@@ -41,7 +41,7 @@ Requires-Dist: hypothesis[zoneinfo]<7,>=6.103.4; python_version == '3.8'
|
|
|
41
41
|
Requires-Dist: jsonschema[format]<5.0,>=4.18.0
|
|
42
42
|
Requires-Dist: junit-xml<2.0,>=1.9
|
|
43
43
|
Requires-Dist: pyrate-limiter<4.0,>=2.10
|
|
44
|
-
Requires-Dist: pytest-subtests<0.
|
|
44
|
+
Requires-Dist: pytest-subtests<0.15.0,>=0.2.1
|
|
45
45
|
Requires-Dist: pytest<9,>=4.6.4
|
|
46
46
|
Requires-Dist: pyyaml<7.0,>=5.1
|
|
47
47
|
Requires-Dist: requests<3,>=2.22
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
schemathesis/__init__.py,sha256=UW2Bq8hDDkcBeAAA7PzpBFXkOOxkmHox-mfQwzHDjL0,1914
|
|
2
2
|
schemathesis/_compat.py,sha256=y4RZd59i2NCnZ91VQhnKeMn_8t3SgvLOk2Xm8nymUHY,1837
|
|
3
3
|
schemathesis/_dependency_versions.py,sha256=pjEkkGAfOQJYNb-9UOo84V8nj_lKHr_TGDVdFwY2UU0,816
|
|
4
|
-
schemathesis/_hypothesis.py,sha256=
|
|
4
|
+
schemathesis/_hypothesis.py,sha256=UTvx-hN-kUMZqBPDcDrg4KFbGfQLLMfMCtD82OSmv_k,24401
|
|
5
5
|
schemathesis/_lazy_import.py,sha256=aMhWYgbU2JOltyWBb32vnWBb6kykOghucEzI_F70yVE,470
|
|
6
6
|
schemathesis/_override.py,sha256=TAjYB3eJQmlw9K_xiR9ptt9Wj7if4U7UFlUhGjpBAoM,1625
|
|
7
7
|
schemathesis/_patches.py,sha256=Hsbpn4UVeXUQD2Kllrbq01CSWsTYENWa0VJTyhX5C2k,895
|
|
@@ -18,7 +18,7 @@ schemathesis/graphql.py,sha256=XiuKcfoOB92iLFC8zpz2msLkM0_V0TLdxPNBqrrGZ8w,216
|
|
|
18
18
|
schemathesis/hooks.py,sha256=p5AXgjVGtka0jn9MOeyBaRUtNbqZTs4iaJqytYTacHc,14856
|
|
19
19
|
schemathesis/lazy.py,sha256=Ddhkk7Tpc_VcRGYkCtKDmP2gpjxVmEZ3b01ZTNjbm8I,19004
|
|
20
20
|
schemathesis/loaders.py,sha256=MoEhcdOEBJxNRn5X-ZNhWB9jZDHQQNpkNfEdQjf_NDw,4590
|
|
21
|
-
schemathesis/models.py,sha256=
|
|
21
|
+
schemathesis/models.py,sha256=4MX3ErKMdueUXGcVPZuvMTbesUglbuj0ukgCmg3nhP8,50014
|
|
22
22
|
schemathesis/parameters.py,sha256=izlu4MFYT1RWrC4RBxrV6weeCal-ODbdLQLMb0PYCZY,2327
|
|
23
23
|
schemathesis/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
24
24
|
schemathesis/sanitization.py,sha256=Lycn1VVfula9B6XpzkxTHja7CZ7RHqbUh9kBic0Yi4M,9056
|
|
@@ -36,7 +36,7 @@ schemathesis/cli/constants.py,sha256=wk-0GsoJIel8wFFerQ6Kf_6eAYUtIWkwMFwyAqv3yj4
|
|
|
36
36
|
schemathesis/cli/context.py,sha256=j_lvYQiPa6Q7P4P_IGCM9V2y2gJSpDbpxIIzR5oFB2I,2567
|
|
37
37
|
schemathesis/cli/debug.py,sha256=_YA-bX1ujHl4bqQDEum7M-I2XHBTEGbvgkhvcvKhmgU,658
|
|
38
38
|
schemathesis/cli/handlers.py,sha256=EXSAFe5TQlHANz1AVlSttfsoDT2oeaeFbqq1N7e2udw,467
|
|
39
|
-
schemathesis/cli/junitxml.py,sha256=
|
|
39
|
+
schemathesis/cli/junitxml.py,sha256=_psBdqGwH4OKySSWeva41mbgGLav86UnWhQyOt99gnU,5331
|
|
40
40
|
schemathesis/cli/options.py,sha256=yL7nrzKkbGCc4nQya9wpTW48XGz_OT9hOFrzPxRrDe4,2853
|
|
41
41
|
schemathesis/cli/reporting.py,sha256=KC3sxSc1u4aFQ-0Q8CQ3G4HTEl7QxlubGnJgNKmVJdQ,3627
|
|
42
42
|
schemathesis/cli/sanitization.py,sha256=Onw_NWZSom6XTVNJ5NHnC0PAhrYAcGzIXJbsBCzLkn4,1005
|
|
@@ -107,7 +107,7 @@ schemathesis/specs/graphql/validation.py,sha256=uINIOt-2E7ZuQV2CxKzwez-7L9tDtqzM
|
|
|
107
107
|
schemathesis/specs/openapi/__init__.py,sha256=HDcx3bqpa6qWPpyMrxAbM3uTo0Lqpg-BUNZhDJSJKnw,279
|
|
108
108
|
schemathesis/specs/openapi/_cache.py,sha256=PAiAu4X_a2PQgD2lG5H3iisXdyg4SaHpU46bRZvfNkM,4320
|
|
109
109
|
schemathesis/specs/openapi/_hypothesis.py,sha256=nU8UDn1PzGCre4IVmwIuO9-CZv1KJe1fYY0d2BojhSo,22981
|
|
110
|
-
schemathesis/specs/openapi/checks.py,sha256=
|
|
110
|
+
schemathesis/specs/openapi/checks.py,sha256=fWtI7rq4wi6qK2E9U_hdJlIyIBVTCB4Klh_3hrCNsps,25349
|
|
111
111
|
schemathesis/specs/openapi/constants.py,sha256=JqM_FHOenqS_MuUE9sxVQ8Hnw0DNM8cnKDwCwPLhID4,783
|
|
112
112
|
schemathesis/specs/openapi/converter.py,sha256=Yxw9lS_JKEyi-oJuACT07fm04bqQDlAu-iHwzkeDvE4,3546
|
|
113
113
|
schemathesis/specs/openapi/definitions.py,sha256=WTkWwCgTc3OMxfKsqh6YDoGfZMTThSYrHGp8h0vLAK0,93935
|
|
@@ -119,7 +119,7 @@ schemathesis/specs/openapi/media_types.py,sha256=dNTxpRQbY3SubdVjh4Cjb38R6Bc9MF9
|
|
|
119
119
|
schemathesis/specs/openapi/parameters.py,sha256=LUahlWKCDSlp94v2IA1Q90pyeECgO6FmrqbzCU-9Z0Y,14658
|
|
120
120
|
schemathesis/specs/openapi/patterns.py,sha256=aEOiJeqI_qcE9bE2Viz6TUA8UppiTHm6QFxrLJryag8,5520
|
|
121
121
|
schemathesis/specs/openapi/references.py,sha256=euxM02kQGMHh4Ss1jWjOY_gyw_HazafKITIsvOEiAvI,9831
|
|
122
|
-
schemathesis/specs/openapi/schemas.py,sha256=
|
|
122
|
+
schemathesis/specs/openapi/schemas.py,sha256=JA9SiBnwYg75kYnd4_0CWOuQv_XTfYwuDeGmFe4RtVo,53724
|
|
123
123
|
schemathesis/specs/openapi/security.py,sha256=Z-6pk2Ga1PTUtBe298KunjVHsNh5A-teegeso7zcPIE,7138
|
|
124
124
|
schemathesis/specs/openapi/serialization.py,sha256=5qGdFHZ3n80UlbSXrO_bkr4Al_7ci_Z3aSUjZczNDQY,11384
|
|
125
125
|
schemathesis/specs/openapi/utils.py,sha256=ER4vJkdFVDIE7aKyxyYatuuHVRNutytezgE52pqZNE8,900
|
|
@@ -153,8 +153,8 @@ schemathesis/transports/auth.py,sha256=urSTO9zgFO1qU69xvnKHPFQV0SlJL3d7_Ojl0tLnZ
|
|
|
153
153
|
schemathesis/transports/content_types.py,sha256=MiKOm-Hy5i75hrROPdpiBZPOTDzOwlCdnthJD12AJzI,2187
|
|
154
154
|
schemathesis/transports/headers.py,sha256=hr_AIDOfUxsJxpHfemIZ_uNG3_vzS_ZeMEKmZjbYiBE,990
|
|
155
155
|
schemathesis/transports/responses.py,sha256=OFD4ZLqwEFpo7F9vaP_SVgjhxAqatxIj38FS4XVq8Qs,1680
|
|
156
|
-
schemathesis-3.39.
|
|
157
|
-
schemathesis-3.39.
|
|
158
|
-
schemathesis-3.39.
|
|
159
|
-
schemathesis-3.39.
|
|
160
|
-
schemathesis-3.39.
|
|
156
|
+
schemathesis-3.39.3.dist-info/METADATA,sha256=pGuuU539A3Wb2FUy6vbkjX0qHjEV8fREory0-ehDFPg,12956
|
|
157
|
+
schemathesis-3.39.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
158
|
+
schemathesis-3.39.3.dist-info/entry_points.txt,sha256=VHyLcOG7co0nOeuk8WjgpRETk5P1E2iCLrn26Zkn5uk,158
|
|
159
|
+
schemathesis-3.39.3.dist-info/licenses/LICENSE,sha256=PsPYgrDhZ7g9uwihJXNG-XVb55wj2uYhkl2DD8oAzY0,1103
|
|
160
|
+
schemathesis-3.39.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|