schemathesis 3.13.0__py3-none-any.whl → 4.4.2__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 (245) hide show
  1. schemathesis/__init__.py +53 -25
  2. schemathesis/auths.py +507 -0
  3. schemathesis/checks.py +190 -25
  4. schemathesis/cli/__init__.py +27 -1016
  5. schemathesis/cli/__main__.py +4 -0
  6. schemathesis/cli/commands/__init__.py +133 -0
  7. schemathesis/cli/commands/data.py +10 -0
  8. schemathesis/cli/commands/run/__init__.py +602 -0
  9. schemathesis/cli/commands/run/context.py +228 -0
  10. schemathesis/cli/commands/run/events.py +60 -0
  11. schemathesis/cli/commands/run/executor.py +157 -0
  12. schemathesis/cli/commands/run/filters.py +53 -0
  13. schemathesis/cli/commands/run/handlers/__init__.py +46 -0
  14. schemathesis/cli/commands/run/handlers/base.py +45 -0
  15. schemathesis/cli/commands/run/handlers/cassettes.py +464 -0
  16. schemathesis/cli/commands/run/handlers/junitxml.py +60 -0
  17. schemathesis/cli/commands/run/handlers/output.py +1750 -0
  18. schemathesis/cli/commands/run/loaders.py +118 -0
  19. schemathesis/cli/commands/run/validation.py +256 -0
  20. schemathesis/cli/constants.py +5 -0
  21. schemathesis/cli/core.py +19 -0
  22. schemathesis/cli/ext/fs.py +16 -0
  23. schemathesis/cli/ext/groups.py +203 -0
  24. schemathesis/cli/ext/options.py +81 -0
  25. schemathesis/config/__init__.py +202 -0
  26. schemathesis/config/_auth.py +51 -0
  27. schemathesis/config/_checks.py +268 -0
  28. schemathesis/config/_diff_base.py +101 -0
  29. schemathesis/config/_env.py +21 -0
  30. schemathesis/config/_error.py +163 -0
  31. schemathesis/config/_generation.py +157 -0
  32. schemathesis/config/_health_check.py +24 -0
  33. schemathesis/config/_operations.py +335 -0
  34. schemathesis/config/_output.py +171 -0
  35. schemathesis/config/_parameters.py +19 -0
  36. schemathesis/config/_phases.py +253 -0
  37. schemathesis/config/_projects.py +543 -0
  38. schemathesis/config/_rate_limit.py +17 -0
  39. schemathesis/config/_report.py +120 -0
  40. schemathesis/config/_validator.py +9 -0
  41. schemathesis/config/_warnings.py +89 -0
  42. schemathesis/config/schema.json +975 -0
  43. schemathesis/core/__init__.py +72 -0
  44. schemathesis/core/adapter.py +34 -0
  45. schemathesis/core/compat.py +32 -0
  46. schemathesis/core/control.py +2 -0
  47. schemathesis/core/curl.py +100 -0
  48. schemathesis/core/deserialization.py +210 -0
  49. schemathesis/core/errors.py +588 -0
  50. schemathesis/core/failures.py +316 -0
  51. schemathesis/core/fs.py +19 -0
  52. schemathesis/core/hooks.py +20 -0
  53. schemathesis/core/jsonschema/__init__.py +13 -0
  54. schemathesis/core/jsonschema/bundler.py +183 -0
  55. schemathesis/core/jsonschema/keywords.py +40 -0
  56. schemathesis/core/jsonschema/references.py +222 -0
  57. schemathesis/core/jsonschema/types.py +41 -0
  58. schemathesis/core/lazy_import.py +15 -0
  59. schemathesis/core/loaders.py +107 -0
  60. schemathesis/core/marks.py +66 -0
  61. schemathesis/core/media_types.py +79 -0
  62. schemathesis/core/output/__init__.py +46 -0
  63. schemathesis/core/output/sanitization.py +54 -0
  64. schemathesis/core/parameters.py +45 -0
  65. schemathesis/core/rate_limit.py +60 -0
  66. schemathesis/core/registries.py +34 -0
  67. schemathesis/core/result.py +27 -0
  68. schemathesis/core/schema_analysis.py +17 -0
  69. schemathesis/core/shell.py +203 -0
  70. schemathesis/core/transforms.py +144 -0
  71. schemathesis/core/transport.py +223 -0
  72. schemathesis/core/validation.py +73 -0
  73. schemathesis/core/version.py +7 -0
  74. schemathesis/engine/__init__.py +28 -0
  75. schemathesis/engine/context.py +152 -0
  76. schemathesis/engine/control.py +44 -0
  77. schemathesis/engine/core.py +201 -0
  78. schemathesis/engine/errors.py +446 -0
  79. schemathesis/engine/events.py +284 -0
  80. schemathesis/engine/observations.py +42 -0
  81. schemathesis/engine/phases/__init__.py +108 -0
  82. schemathesis/engine/phases/analysis.py +28 -0
  83. schemathesis/engine/phases/probes.py +172 -0
  84. schemathesis/engine/phases/stateful/__init__.py +68 -0
  85. schemathesis/engine/phases/stateful/_executor.py +364 -0
  86. schemathesis/engine/phases/stateful/context.py +85 -0
  87. schemathesis/engine/phases/unit/__init__.py +220 -0
  88. schemathesis/engine/phases/unit/_executor.py +459 -0
  89. schemathesis/engine/phases/unit/_pool.py +82 -0
  90. schemathesis/engine/recorder.py +254 -0
  91. schemathesis/errors.py +47 -0
  92. schemathesis/filters.py +395 -0
  93. schemathesis/generation/__init__.py +25 -0
  94. schemathesis/generation/case.py +478 -0
  95. schemathesis/generation/coverage.py +1528 -0
  96. schemathesis/generation/hypothesis/__init__.py +121 -0
  97. schemathesis/generation/hypothesis/builder.py +992 -0
  98. schemathesis/generation/hypothesis/examples.py +56 -0
  99. schemathesis/generation/hypothesis/given.py +66 -0
  100. schemathesis/generation/hypothesis/reporting.py +285 -0
  101. schemathesis/generation/meta.py +227 -0
  102. schemathesis/generation/metrics.py +93 -0
  103. schemathesis/generation/modes.py +20 -0
  104. schemathesis/generation/overrides.py +127 -0
  105. schemathesis/generation/stateful/__init__.py +37 -0
  106. schemathesis/generation/stateful/state_machine.py +294 -0
  107. schemathesis/graphql/__init__.py +15 -0
  108. schemathesis/graphql/checks.py +109 -0
  109. schemathesis/graphql/loaders.py +285 -0
  110. schemathesis/hooks.py +270 -91
  111. schemathesis/openapi/__init__.py +13 -0
  112. schemathesis/openapi/checks.py +467 -0
  113. schemathesis/openapi/generation/__init__.py +0 -0
  114. schemathesis/openapi/generation/filters.py +72 -0
  115. schemathesis/openapi/loaders.py +315 -0
  116. schemathesis/pytest/__init__.py +5 -0
  117. schemathesis/pytest/control_flow.py +7 -0
  118. schemathesis/pytest/lazy.py +341 -0
  119. schemathesis/pytest/loaders.py +36 -0
  120. schemathesis/pytest/plugin.py +357 -0
  121. schemathesis/python/__init__.py +0 -0
  122. schemathesis/python/asgi.py +12 -0
  123. schemathesis/python/wsgi.py +12 -0
  124. schemathesis/schemas.py +683 -247
  125. schemathesis/specs/graphql/__init__.py +0 -1
  126. schemathesis/specs/graphql/nodes.py +27 -0
  127. schemathesis/specs/graphql/scalars.py +86 -0
  128. schemathesis/specs/graphql/schemas.py +395 -123
  129. schemathesis/specs/graphql/validation.py +33 -0
  130. schemathesis/specs/openapi/__init__.py +9 -1
  131. schemathesis/specs/openapi/_hypothesis.py +578 -317
  132. schemathesis/specs/openapi/adapter/__init__.py +10 -0
  133. schemathesis/specs/openapi/adapter/parameters.py +729 -0
  134. schemathesis/specs/openapi/adapter/protocol.py +59 -0
  135. schemathesis/specs/openapi/adapter/references.py +19 -0
  136. schemathesis/specs/openapi/adapter/responses.py +368 -0
  137. schemathesis/specs/openapi/adapter/security.py +144 -0
  138. schemathesis/specs/openapi/adapter/v2.py +30 -0
  139. schemathesis/specs/openapi/adapter/v3_0.py +30 -0
  140. schemathesis/specs/openapi/adapter/v3_1.py +30 -0
  141. schemathesis/specs/openapi/analysis.py +96 -0
  142. schemathesis/specs/openapi/checks.py +753 -74
  143. schemathesis/specs/openapi/converter.py +176 -37
  144. schemathesis/specs/openapi/definitions.py +599 -4
  145. schemathesis/specs/openapi/examples.py +581 -165
  146. schemathesis/specs/openapi/expressions/__init__.py +52 -5
  147. schemathesis/specs/openapi/expressions/extractors.py +25 -0
  148. schemathesis/specs/openapi/expressions/lexer.py +34 -31
  149. schemathesis/specs/openapi/expressions/nodes.py +97 -46
  150. schemathesis/specs/openapi/expressions/parser.py +35 -13
  151. schemathesis/specs/openapi/formats.py +122 -0
  152. schemathesis/specs/openapi/media_types.py +75 -0
  153. schemathesis/specs/openapi/negative/__init__.py +117 -68
  154. schemathesis/specs/openapi/negative/mutations.py +294 -104
  155. schemathesis/specs/openapi/negative/utils.py +3 -6
  156. schemathesis/specs/openapi/patterns.py +458 -0
  157. schemathesis/specs/openapi/references.py +60 -81
  158. schemathesis/specs/openapi/schemas.py +648 -650
  159. schemathesis/specs/openapi/serialization.py +53 -30
  160. schemathesis/specs/openapi/stateful/__init__.py +404 -69
  161. schemathesis/specs/openapi/stateful/control.py +87 -0
  162. schemathesis/specs/openapi/stateful/dependencies/__init__.py +232 -0
  163. schemathesis/specs/openapi/stateful/dependencies/inputs.py +428 -0
  164. schemathesis/specs/openapi/stateful/dependencies/models.py +341 -0
  165. schemathesis/specs/openapi/stateful/dependencies/naming.py +491 -0
  166. schemathesis/specs/openapi/stateful/dependencies/outputs.py +34 -0
  167. schemathesis/specs/openapi/stateful/dependencies/resources.py +339 -0
  168. schemathesis/specs/openapi/stateful/dependencies/schemas.py +447 -0
  169. schemathesis/specs/openapi/stateful/inference.py +254 -0
  170. schemathesis/specs/openapi/stateful/links.py +219 -78
  171. schemathesis/specs/openapi/types/__init__.py +3 -0
  172. schemathesis/specs/openapi/types/common.py +23 -0
  173. schemathesis/specs/openapi/types/v2.py +129 -0
  174. schemathesis/specs/openapi/types/v3.py +134 -0
  175. schemathesis/specs/openapi/utils.py +7 -6
  176. schemathesis/specs/openapi/warnings.py +75 -0
  177. schemathesis/transport/__init__.py +224 -0
  178. schemathesis/transport/asgi.py +26 -0
  179. schemathesis/transport/prepare.py +126 -0
  180. schemathesis/transport/requests.py +278 -0
  181. schemathesis/transport/serialization.py +329 -0
  182. schemathesis/transport/wsgi.py +175 -0
  183. schemathesis-4.4.2.dist-info/METADATA +213 -0
  184. schemathesis-4.4.2.dist-info/RECORD +192 -0
  185. {schemathesis-3.13.0.dist-info → schemathesis-4.4.2.dist-info}/WHEEL +1 -1
  186. schemathesis-4.4.2.dist-info/entry_points.txt +6 -0
  187. {schemathesis-3.13.0.dist-info → schemathesis-4.4.2.dist-info/licenses}/LICENSE +1 -1
  188. schemathesis/_compat.py +0 -41
  189. schemathesis/_hypothesis.py +0 -115
  190. schemathesis/cli/callbacks.py +0 -188
  191. schemathesis/cli/cassettes.py +0 -253
  192. schemathesis/cli/context.py +0 -36
  193. schemathesis/cli/debug.py +0 -21
  194. schemathesis/cli/handlers.py +0 -11
  195. schemathesis/cli/junitxml.py +0 -41
  196. schemathesis/cli/options.py +0 -51
  197. schemathesis/cli/output/__init__.py +0 -1
  198. schemathesis/cli/output/default.py +0 -508
  199. schemathesis/cli/output/short.py +0 -40
  200. schemathesis/constants.py +0 -79
  201. schemathesis/exceptions.py +0 -207
  202. schemathesis/extra/_aiohttp.py +0 -27
  203. schemathesis/extra/_flask.py +0 -10
  204. schemathesis/extra/_server.py +0 -16
  205. schemathesis/extra/pytest_plugin.py +0 -216
  206. schemathesis/failures.py +0 -131
  207. schemathesis/fixups/__init__.py +0 -29
  208. schemathesis/fixups/fast_api.py +0 -30
  209. schemathesis/lazy.py +0 -227
  210. schemathesis/models.py +0 -1041
  211. schemathesis/parameters.py +0 -88
  212. schemathesis/runner/__init__.py +0 -460
  213. schemathesis/runner/events.py +0 -240
  214. schemathesis/runner/impl/__init__.py +0 -3
  215. schemathesis/runner/impl/core.py +0 -755
  216. schemathesis/runner/impl/solo.py +0 -85
  217. schemathesis/runner/impl/threadpool.py +0 -367
  218. schemathesis/runner/serialization.py +0 -189
  219. schemathesis/serializers.py +0 -233
  220. schemathesis/service/__init__.py +0 -3
  221. schemathesis/service/client.py +0 -46
  222. schemathesis/service/constants.py +0 -12
  223. schemathesis/service/events.py +0 -39
  224. schemathesis/service/handler.py +0 -39
  225. schemathesis/service/models.py +0 -7
  226. schemathesis/service/serialization.py +0 -153
  227. schemathesis/service/worker.py +0 -40
  228. schemathesis/specs/graphql/loaders.py +0 -215
  229. schemathesis/specs/openapi/constants.py +0 -7
  230. schemathesis/specs/openapi/expressions/context.py +0 -12
  231. schemathesis/specs/openapi/expressions/pointers.py +0 -29
  232. schemathesis/specs/openapi/filters.py +0 -44
  233. schemathesis/specs/openapi/links.py +0 -302
  234. schemathesis/specs/openapi/loaders.py +0 -453
  235. schemathesis/specs/openapi/parameters.py +0 -413
  236. schemathesis/specs/openapi/security.py +0 -129
  237. schemathesis/specs/openapi/validation.py +0 -24
  238. schemathesis/stateful.py +0 -349
  239. schemathesis/targets.py +0 -32
  240. schemathesis/types.py +0 -38
  241. schemathesis/utils.py +0 -436
  242. schemathesis-3.13.0.dist-info/METADATA +0 -202
  243. schemathesis-3.13.0.dist-info/RECORD +0 -91
  244. schemathesis-3.13.0.dist-info/entry_points.txt +0 -6
  245. /schemathesis/{extra → cli/ext}/__init__.py +0 -0
schemathesis/stateful.py DELETED
@@ -1,349 +0,0 @@
1
- import enum
2
- import json
3
- from typing import TYPE_CHECKING, Any, Callable, ClassVar, Dict, Generator, List, Optional, Tuple
4
-
5
- import attr
6
- import hypothesis
7
- from hypothesis.stateful import RuleBasedStateMachine
8
- from requests.structures import CaseInsensitiveDict
9
- from starlette.applications import Starlette
10
-
11
- from .constants import DataGenerationMethod
12
- from .exceptions import InvalidSchema
13
- from .models import APIOperation, Case, CheckFunction
14
- from .utils import NOT_SET, GenericResponse, Ok, Result
15
-
16
- if TYPE_CHECKING:
17
- from .schemas import BaseSchema
18
-
19
-
20
- class Stateful(enum.Enum):
21
- links = 1
22
-
23
-
24
- @attr.s(slots=True, hash=False) # pragma: no mutate
25
- class ParsedData:
26
- """A structure that holds information parsed from a test outcome.
27
-
28
- It is used later to create a new version of an API operation that will reuse this data.
29
- """
30
-
31
- parameters: Dict[str, Any] = attr.ib() # pragma: no mutate
32
- body: Any = attr.ib(default=NOT_SET) # pragma: no mutate
33
-
34
- def __hash__(self) -> int:
35
- """Custom hash simplifies deduplication of parsed data."""
36
- value = hash(tuple(self.parameters.items())) # parameters never contain nested dicts / lists
37
- if self.body is not NOT_SET:
38
- if isinstance(self.body, (dict, list)):
39
- # The simplest way to get a hash of a potentially nested structure
40
- value ^= hash(json.dumps(self.body, sort_keys=True))
41
- else:
42
- # These types should be hashable
43
- value ^= hash(self.body)
44
- return value
45
-
46
-
47
- @attr.s(slots=True) # pragma: no mutate
48
- class StatefulTest:
49
- """A template for a test that will be executed after another one by reusing the outcomes from it."""
50
-
51
- name: str = attr.ib() # pragma: no mutate
52
-
53
- def parse(self, case: Case, response: GenericResponse) -> ParsedData:
54
- raise NotImplementedError
55
-
56
- def make_operation(self, collected: List[ParsedData]) -> APIOperation:
57
- raise NotImplementedError
58
-
59
-
60
- @attr.s(slots=True) # pragma: no mutate
61
- class StatefulData:
62
- """Storage for data that will be used in later tests."""
63
-
64
- stateful_test: StatefulTest = attr.ib() # pragma: no mutate
65
- container: List[ParsedData] = attr.ib(factory=list) # pragma: no mutate
66
-
67
- def make_operation(self) -> APIOperation:
68
- return self.stateful_test.make_operation(self.container)
69
-
70
- def store(self, case: Case, response: GenericResponse) -> None:
71
- """Parse and store data for a stateful test."""
72
- parsed = self.stateful_test.parse(case, response)
73
- self.container.append(parsed)
74
-
75
-
76
- @attr.s(slots=True) # pragma: no mutate
77
- class Feedback:
78
- """Handler for feedback from tests.
79
-
80
- Provides a way to control runner's behavior from tests.
81
- """
82
-
83
- stateful: Optional[Stateful] = attr.ib() # pragma: no mutate
84
- operation: APIOperation = attr.ib(repr=False) # pragma: no mutate
85
- stateful_tests: Dict[str, StatefulData] = attr.ib(factory=dict, repr=False) # pragma: no mutate
86
-
87
- def add_test_case(self, case: Case, response: GenericResponse) -> None:
88
- """Store test data to reuse it in the future additional tests."""
89
- for stateful_test in case.operation.get_stateful_tests(response, self.stateful):
90
- data = self.stateful_tests.setdefault(stateful_test.name, StatefulData(stateful_test))
91
- data.store(case, response)
92
-
93
- def get_stateful_tests(
94
- self, test: Callable, settings: Optional[hypothesis.settings], seed: Optional[int]
95
- ) -> Generator[Tuple[Result[Tuple[APIOperation, Callable], InvalidSchema], DataGenerationMethod], None, None]:
96
- """Generate additional tests that use data from the previous ones."""
97
- from ._hypothesis import create_test # pylint: disable=import-outside-toplevel
98
-
99
- for data in self.stateful_tests.values():
100
- operation = data.make_operation()
101
- for data_generation_method in operation.schema.data_generation_methods:
102
- test_function = create_test(
103
- operation=operation,
104
- test=test,
105
- settings=settings,
106
- seed=seed,
107
- data_generation_method=data_generation_method,
108
- )
109
- yield Ok((operation, test_function)), data_generation_method
110
-
111
-
112
- @attr.s(slots=True) # pragma: no mutate
113
- class StepResult:
114
- """Output from a single transition of a state machine."""
115
-
116
- response: GenericResponse = attr.ib() # pragma: no mutate
117
- case: Case = attr.ib() # pragma: no mutate
118
-
119
-
120
- class Direction:
121
- name: str
122
- status_code: str
123
- operation: APIOperation
124
-
125
- def set_data(self, case: Case, **kwargs: Any) -> None:
126
- raise NotImplementedError
127
-
128
-
129
- def _print_case(case: Case) -> str:
130
- operation = f"state.schema['{case.operation.path}']['{case.operation.method.upper()}']"
131
- data = [
132
- f"{name}={repr(getattr(case, name))}"
133
- for name in ("path_parameters", "headers", "cookies", "query", "body", "media_type")
134
- if getattr(case, name) not in (None, NOT_SET)
135
- ]
136
- return f"{operation}.make_case({', '.join(data)})"
137
-
138
-
139
- @attr.s(slots=True, repr=False) # pragma: no mutate
140
- class _DirectionWrapper:
141
- """Purely to avoid modification of `Direction.__repr__`."""
142
-
143
- direction: Direction = attr.ib() # pragma: no mutate
144
-
145
- def __repr__(self) -> str:
146
- path = self.direction.operation.path
147
- method = self.direction.operation.method.upper()
148
- return f"state.schema['{path}']['{method}'].links['{self.direction.status_code}']['{self.direction.name}']"
149
-
150
-
151
- class APIStateMachine(RuleBasedStateMachine):
152
- """The base class for state machines generated from API schemas.
153
-
154
- Exposes additional extension points in the testing process.
155
- """
156
-
157
- # This is a convenience attribute, which happened to clash with `RuleBasedStateMachine` instance level attribute
158
- # They don't interfere, since it is properly overridden on the Hypothesis side, but it is likely that this
159
- # attribute will be renamed in the future
160
- bundles: ClassVar[Dict[str, CaseInsensitiveDict]] # type: ignore
161
- schema: "BaseSchema"
162
-
163
- def __init__(self) -> None:
164
- super().__init__() # type: ignore
165
- self.setup()
166
-
167
- def _pretty_print(self, value: Any) -> str:
168
- if isinstance(value, Case):
169
- return _print_case(value)
170
- if isinstance(value, tuple) and len(value) == 2:
171
- result, direction = value
172
- wrapper = _DirectionWrapper(direction)
173
- return super()._pretty_print((result, wrapper)) # type: ignore
174
- return super()._pretty_print(value) # type: ignore
175
-
176
- def setup(self) -> None:
177
- """Hook method that runs unconditionally in the beginning of each test scenario.
178
-
179
- Does nothing by default.
180
- """
181
-
182
- def teardown(self) -> None:
183
- pass
184
-
185
- # To provide the return type in the rendered documentation
186
- teardown.__doc__ = RuleBasedStateMachine.teardown.__doc__
187
-
188
- def transform(self, result: StepResult, direction: Direction, case: Case) -> Case:
189
- raise NotImplementedError
190
-
191
- def _step(self, case: Case, previous: Optional[Tuple[StepResult, Direction]] = None) -> StepResult:
192
- # This method is a proxy that is used under the hood during the state machine initialization.
193
- # The whole point of having it is to make it possible to override `step`; otherwise, custom "step" is ignored.
194
- # It happens because, at the point of initialization, the final class is not yet created.
195
- return self.step(case, previous)
196
-
197
- def step(self, case: Case, previous: Optional[Tuple[StepResult, Direction]] = None) -> StepResult:
198
- """A single state machine step.
199
-
200
- :param Case case: Generated test case data that should be sent in an API call to the tested API operation.
201
- :param previous: Optional result from the previous step and the direction in which this step should be done.
202
-
203
- Schemathesis prepares data, makes a call and validates the received response.
204
- It is the most high-level point to extend the testing process. You probably don't need it in most cases.
205
- """
206
- if previous is not None:
207
- result, direction = previous
208
- case = self.transform(result, direction, case)
209
- self.before_call(case)
210
- kwargs = self.get_call_kwargs(case)
211
- response = self.call(case, **kwargs)
212
- self.after_call(response, case)
213
- self.validate_response(response, case)
214
- return self.store_result(response, case)
215
-
216
- def before_call(self, case: Case) -> None:
217
- """Hook method for modifying the case data before making a request.
218
-
219
- :param Case case: Generated test case data that should be sent in an API call to the tested API operation.
220
-
221
- Use it if you want to inject static data, for example,
222
- a query parameter that should always be used in API calls:
223
-
224
- .. code-block:: python
225
-
226
- class APIWorkflow(schema.as_state_machine()):
227
- def before_call(self, case):
228
- case.query = case.query or {}
229
- case.query["test"] = "true"
230
-
231
- You can also modify data only for some operations:
232
-
233
- .. code-block:: python
234
-
235
- class APIWorkflow(schema.as_state_machine()):
236
- def before_call(self, case):
237
- if case.method == "PUT" and case.path == "/items":
238
- case.body["is_fake"] = True
239
- """
240
-
241
- def after_call(self, response: GenericResponse, case: Case) -> None:
242
- """Hook method for additional actions with case or response instances.
243
-
244
- :param response: Response from the application under test.
245
- :param Case case: Generated test case data that should be sent in an API call to the tested API operation.
246
-
247
- For example, you can log all response statuses by using this hook:
248
-
249
- .. code-block:: python
250
-
251
- import logging
252
-
253
- logger = logging.getLogger(__file__)
254
- logger.setLevel(logging.INFO)
255
-
256
-
257
- class APIWorkflow(schema.as_state_machine()):
258
- def after_call(self, response, case):
259
- logger.info(
260
- "%s %s -> %d",
261
- case.method,
262
- case.path,
263
- response.status_code,
264
- )
265
-
266
-
267
- # POST /users/ -> 201
268
- # GET /users/{user_id} -> 200
269
- # PATCH /users/{user_id} -> 200
270
- # GET /users/{user_id} -> 200
271
- # PATCH /users/{user_id} -> 500
272
- """
273
-
274
- def call(self, case: Case, **kwargs: Any) -> GenericResponse:
275
- """Make a request to the API.
276
-
277
- :param Case case: Generated test case data that should be sent in an API call to the tested API operation.
278
- :param kwargs: Keyword arguments that will be passed to the appropriate ``case.call_*`` method.
279
- :return: Response from the application under test.
280
-
281
- Note that WSGI/ASGI applications are detected automatically in this method. Depending on the result of this
282
- detection the state machine will call ``call``, ``call_wsgi`` or ``call_asgi`` methods.
283
-
284
- Usually, you don't need to override this method unless you are building a different state machine on top of this
285
- one and want to customize the transport layer itself.
286
- """
287
- method = self._get_call_method(case)
288
- return method(**kwargs)
289
-
290
- def get_call_kwargs(self, case: Case) -> Dict[str, Any]:
291
- """Create custom keyword arguments that will be passed to the :meth:`Case.call` method.
292
-
293
- Mostly they are proxied to the :func:`requests.request` call.
294
-
295
- :param Case case: Generated test case data that should be sent in an API call to the tested API operation.
296
-
297
- .. code-block:: python
298
-
299
- class APIWorkflow(schema.as_state_machine()):
300
- def get_call_kwargs(self, case):
301
- return {"verify": False}
302
-
303
- The above example disables the server's TLS certificate verification.
304
- """
305
- return {}
306
-
307
- def _get_call_method(self, case: Case) -> Callable:
308
- if case.app is not None:
309
- if isinstance(case.app, Starlette):
310
- return case.call_asgi
311
- return case.call_wsgi
312
- return case.call
313
-
314
- def validate_response(
315
- self, response: GenericResponse, case: Case, additional_checks: Tuple[CheckFunction, ...] = ()
316
- ) -> None:
317
- """Validate an API response.
318
-
319
- :param response: Response from the application under test.
320
- :param Case case: Generated test case data that should be sent in an API call to the tested API operation.
321
- :param additional_checks: A list of checks that will be run together with the default ones.
322
- :raises CheckFailed: If any of the supplied checks failed.
323
-
324
- If you need to change the default checks or provide custom validation rules, you can do it here.
325
-
326
- .. code-block:: python
327
-
328
- def my_check(response, case):
329
- ... # some assertions
330
-
331
-
332
- class APIWorkflow(schema.as_state_machine()):
333
- def validate_response(self, response, case):
334
- case.validate_response(response, checks=(my_check,))
335
-
336
- The state machine from the example above will execute only the ``my_check`` check instead of all
337
- available checks.
338
-
339
- Each check function should accept ``response`` as the first argument and ``case`` as the second one and raise
340
- ``AssertionError`` if the check fails.
341
-
342
- **Note** that it is preferred to pass check functions as an argument to ``case.validate_response``.
343
- In this case, all checks will be executed, and you'll receive a grouped exception that contains results from
344
- all provided checks rather than only the first encountered exception.
345
- """
346
- case.validate_response(response, additional_checks=additional_checks)
347
-
348
- def store_result(self, response: GenericResponse, case: Case) -> StepResult:
349
- return StepResult(response, case)
schemathesis/targets.py DELETED
@@ -1,32 +0,0 @@
1
- from typing import TYPE_CHECKING, Callable, Tuple
2
-
3
- import attr
4
-
5
- from .utils import GenericResponse
6
-
7
- if TYPE_CHECKING:
8
- from .models import Case
9
-
10
-
11
- @attr.s(slots=True) # pragma: no mutate
12
- class TargetContext:
13
- """Context for targeted testing.
14
-
15
- :ivar Case case: Generated example that is being processed.
16
- :ivar GenericResponse response: API response.
17
- :ivar float response_time: API response time.
18
- """
19
-
20
- case: "Case" = attr.ib() # pragma: no mutate
21
- response: GenericResponse = attr.ib() # pragma: no mutate
22
- response_time: float = attr.ib() # pragma: no mutate
23
-
24
-
25
- def response_time(context: TargetContext) -> float:
26
- return context.response_time
27
-
28
-
29
- Target = Callable[[TargetContext], float]
30
- DEFAULT_TARGETS = ()
31
- OPTIONAL_TARGETS = (response_time,)
32
- ALL_TARGETS: Tuple[Target, ...] = DEFAULT_TARGETS + OPTIONAL_TARGETS
schemathesis/types.py DELETED
@@ -1,38 +0,0 @@
1
- from pathlib import Path
2
- from typing import TYPE_CHECKING, Any, Callable, Dict, Iterable, List, Set, Tuple, Union
3
-
4
- from hypothesis.strategies import SearchStrategy
5
-
6
- if TYPE_CHECKING:
7
- from . import DataGenerationMethod
8
- from .hooks import HookContext
9
-
10
- PathLike = Union[Path, str] # pragma: no mutate
11
-
12
- Query = Dict[str, Any] # pragma: no mutate
13
- # Body can be of any Python type that corresponds to JSON Schema types + `bytes`
14
- Body = Union[List, Dict[str, Any], str, int, float, bool, bytes] # pragma: no mutate
15
- PathParameters = Dict[str, Any] # pragma: no mutate
16
- Headers = Dict[str, Any] # pragma: no mutate
17
- Cookies = Dict[str, Any] # pragma: no mutate
18
- FormData = Dict[str, Any] # pragma: no mutate
19
-
20
-
21
- class NotSet:
22
- pass
23
-
24
-
25
- RequestCert = Union[str, Tuple[str, str]]
26
-
27
-
28
- # A filter for path / method
29
- Filter = Union[str, List[str], Tuple[str], Set[str], NotSet] # pragma: no mutate
30
-
31
- Hook = Union[
32
- Callable[[SearchStrategy], SearchStrategy], Callable[[SearchStrategy, "HookContext"], SearchStrategy]
33
- ] # pragma: no mutate
34
-
35
- RawAuth = Tuple[str, str] # pragma: no mutate
36
- # Generic test with any arguments and no return
37
- GenericTest = Callable[..., None] # pragma: no mutate
38
- DataGenerationMethodInput = Union["DataGenerationMethod", Iterable["DataGenerationMethod"]]