schemathesis 3.35.0__py3-none-any.whl → 3.35.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.
- schemathesis/_hypothesis.py +35 -11
- schemathesis/cli/__init__.py +352 -357
- schemathesis/cli/cassettes.py +2 -0
- schemathesis/cli/context.py +7 -3
- schemathesis/cli/output/default.py +13 -2
- schemathesis/generation/coverage.py +170 -100
- schemathesis/models.py +14 -1
- schemathesis/runner/events.py +3 -1
- schemathesis/runner/serialization.py +3 -1
- schemathesis/schemas.py +3 -9
- schemathesis/specs/graphql/loaders.py +2 -1
- schemathesis/specs/openapi/_hypothesis.py +3 -1
- schemathesis/specs/openapi/examples.py +3 -1
- schemathesis/specs/openapi/loaders.py +3 -1
- schemathesis/specs/openapi/parameters.py +2 -0
- schemathesis/stateful/context.py +3 -0
- schemathesis/stateful/runner.py +8 -1
- schemathesis/types.py +8 -0
- {schemathesis-3.35.0.dist-info → schemathesis-3.35.2.dist-info}/METADATA +69 -168
- {schemathesis-3.35.0.dist-info → schemathesis-3.35.2.dist-info}/RECORD +23 -23
- {schemathesis-3.35.0.dist-info → schemathesis-3.35.2.dist-info}/WHEEL +0 -0
- {schemathesis-3.35.0.dist-info → schemathesis-3.35.2.dist-info}/entry_points.txt +0 -0
- {schemathesis-3.35.0.dist-info → schemathesis-3.35.2.dist-info}/licenses/LICENSE +0 -0
schemathesis/cli/__init__.py
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import base64
|
|
4
|
-
import enum
|
|
5
4
|
import io
|
|
6
5
|
import os
|
|
7
6
|
import sys
|
|
@@ -141,16 +140,11 @@ def schemathesis(pre_run: str | None = None) -> None:
|
|
|
141
140
|
load_hook(hooks)
|
|
142
141
|
|
|
143
142
|
|
|
144
|
-
|
|
145
|
-
filtering = "Testing scope", "Customize the scope of the API testing."
|
|
146
|
-
validation = "Response & Schema validation", "These options specify how API responses and schemas are validated."
|
|
147
|
-
hypothesis = "Hypothesis engine", "Configuration of the underlying Hypothesis engine."
|
|
148
|
-
generic = "Generic", None
|
|
143
|
+
GROUPS: list[str] = []
|
|
149
144
|
|
|
150
145
|
|
|
151
|
-
class
|
|
146
|
+
class CommandWithGroupedOptions(click.Command):
|
|
152
147
|
def format_options(self, ctx: click.Context, formatter: click.HelpFormatter) -> None:
|
|
153
|
-
# Group options first
|
|
154
148
|
groups = defaultdict(list)
|
|
155
149
|
for param in self.get_params(ctx):
|
|
156
150
|
rv = param.get_help_record(ctx)
|
|
@@ -158,32 +152,43 @@ class CommandWithCustomHelp(click.Command):
|
|
|
158
152
|
if isinstance(param, GroupedOption):
|
|
159
153
|
group = param.group
|
|
160
154
|
else:
|
|
161
|
-
group =
|
|
155
|
+
group = "Global options"
|
|
162
156
|
groups[group].append(rv)
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
title, description = group.value
|
|
167
|
-
with formatter.section(title):
|
|
168
|
-
if description:
|
|
169
|
-
formatter.write_paragraph()
|
|
170
|
-
formatter.write_text(description)
|
|
171
|
-
formatter.write_paragraph()
|
|
172
|
-
formatter.write_dl(opts)
|
|
157
|
+
for group in GROUPS:
|
|
158
|
+
with formatter.section(group or "Options"):
|
|
159
|
+
formatter.write_dl(groups[group], col_max=40)
|
|
173
160
|
|
|
174
161
|
|
|
175
162
|
class GroupedOption(click.Option):
|
|
176
|
-
def __init__(self, *args: Any, group:
|
|
163
|
+
def __init__(self, *args: Any, group: str | None = None, **kwargs: Any):
|
|
177
164
|
super().__init__(*args, **kwargs)
|
|
178
165
|
self.group = group
|
|
179
166
|
|
|
180
167
|
|
|
181
|
-
|
|
168
|
+
def group(name: str) -> Callable:
|
|
169
|
+
GROUPS.append(name)
|
|
170
|
+
|
|
171
|
+
def _inner(cmd: Callable) -> Callable:
|
|
172
|
+
for param in reversed(cmd.__click_params__): # type: ignore[attr-defined]
|
|
173
|
+
if not isinstance(param, GroupedOption) or param.group is not None:
|
|
174
|
+
break
|
|
175
|
+
param.group = name
|
|
176
|
+
return cmd
|
|
177
|
+
|
|
178
|
+
return _inner
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def grouped_option(*args: Any, **kwargs: Any) -> Callable:
|
|
182
|
+
kwargs.setdefault("cls", GroupedOption)
|
|
183
|
+
return click.option(*args, **kwargs)
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
with_request_proxy = grouped_option(
|
|
182
187
|
"--request-proxy",
|
|
183
188
|
help="Set the proxy for all network requests.",
|
|
184
189
|
type=str,
|
|
185
190
|
)
|
|
186
|
-
with_request_tls_verify =
|
|
191
|
+
with_request_tls_verify = grouped_option(
|
|
187
192
|
"--request-tls-verify",
|
|
188
193
|
help="Configures TLS certificate verification for server requests. Can specify path to CA_BUNDLE for custom certs.",
|
|
189
194
|
type=str,
|
|
@@ -191,7 +196,7 @@ with_request_tls_verify = click.option(
|
|
|
191
196
|
show_default=True,
|
|
192
197
|
callback=callbacks.convert_boolean_string,
|
|
193
198
|
)
|
|
194
|
-
with_request_cert =
|
|
199
|
+
with_request_cert = grouped_option(
|
|
195
200
|
"--request-cert",
|
|
196
201
|
help="File path of unencrypted client certificate for authentication. "
|
|
197
202
|
"The certificate can be bundled with a private key (e.g. PEM) or the private "
|
|
@@ -200,7 +205,7 @@ with_request_cert = click.option(
|
|
|
200
205
|
default=None,
|
|
201
206
|
show_default=False,
|
|
202
207
|
)
|
|
203
|
-
with_request_cert_key =
|
|
208
|
+
with_request_cert_key = grouped_option(
|
|
204
209
|
"--request-cert-key",
|
|
205
210
|
help="Specifies the file path of the private key for the client certificate.",
|
|
206
211
|
type=click.Path(exists=True),
|
|
@@ -208,7 +213,7 @@ with_request_cert_key = click.option(
|
|
|
208
213
|
show_default=False,
|
|
209
214
|
callback=callbacks.validate_request_cert_key,
|
|
210
215
|
)
|
|
211
|
-
with_hosts_file =
|
|
216
|
+
with_hosts_file = grouped_option(
|
|
212
217
|
"--hosts-file",
|
|
213
218
|
help="Path to a file to store the Schemathesis.io auth configuration.",
|
|
214
219
|
type=click.Path(dir_okay=False, writable=True),
|
|
@@ -230,13 +235,11 @@ def _with_filter(*, by: str, mode: Literal["include", "exclude"], modifier: Lite
|
|
|
230
235
|
param += f"-{modifier}"
|
|
231
236
|
prop += " pattern"
|
|
232
237
|
help_text = f"{prop} to {action} testing."
|
|
233
|
-
return
|
|
238
|
+
return grouped_option(
|
|
234
239
|
param,
|
|
235
240
|
help=help_text,
|
|
236
241
|
type=str,
|
|
237
242
|
multiple=modifier is None,
|
|
238
|
-
cls=GroupedOption,
|
|
239
|
-
group=ParameterGroup.filtering,
|
|
240
243
|
)
|
|
241
244
|
|
|
242
245
|
|
|
@@ -258,10 +261,58 @@ class ReportToService:
|
|
|
258
261
|
REPORT_TO_SERVICE = ReportToService()
|
|
259
262
|
|
|
260
263
|
|
|
261
|
-
@schemathesis.command(
|
|
264
|
+
@schemathesis.command(
|
|
265
|
+
short_help="Execute automated tests based on API specifications.",
|
|
266
|
+
cls=CommandWithGroupedOptions,
|
|
267
|
+
context_settings={"terminal_width": output.default.get_terminal_width(), **CONTEXT_SETTINGS},
|
|
268
|
+
)
|
|
262
269
|
@click.argument("schema", type=str)
|
|
263
270
|
@click.argument("api_name", type=str, required=False, envvar=API_NAME_ENV_VAR)
|
|
264
|
-
@
|
|
271
|
+
@group("Options")
|
|
272
|
+
@grouped_option(
|
|
273
|
+
"--workers",
|
|
274
|
+
"-w",
|
|
275
|
+
"workers_num",
|
|
276
|
+
help="Sets the number of concurrent workers for testing. Auto-adjusts if 'auto' is specified.",
|
|
277
|
+
type=CustomHelpMessageChoice(
|
|
278
|
+
["auto"] + list(map(str, range(MIN_WORKERS, MAX_WORKERS + 1))),
|
|
279
|
+
choices_repr=f"[auto|{MIN_WORKERS}-{MAX_WORKERS}]",
|
|
280
|
+
),
|
|
281
|
+
default=str(DEFAULT_WORKERS),
|
|
282
|
+
show_default=True,
|
|
283
|
+
callback=callbacks.convert_workers,
|
|
284
|
+
)
|
|
285
|
+
@grouped_option(
|
|
286
|
+
"--dry-run",
|
|
287
|
+
"dry_run",
|
|
288
|
+
is_flag=True,
|
|
289
|
+
default=False,
|
|
290
|
+
help="Simulates test execution without making any actual requests, useful for validating data generation.",
|
|
291
|
+
)
|
|
292
|
+
@grouped_option(
|
|
293
|
+
"--experimental",
|
|
294
|
+
"experiments",
|
|
295
|
+
help="Enable experimental features.",
|
|
296
|
+
type=click.Choice(
|
|
297
|
+
[
|
|
298
|
+
experimental.OPEN_API_3_1.name,
|
|
299
|
+
experimental.SCHEMA_ANALYSIS.name,
|
|
300
|
+
experimental.STATEFUL_TEST_RUNNER.name,
|
|
301
|
+
experimental.STATEFUL_ONLY.name,
|
|
302
|
+
experimental.COVERAGE_PHASE.name,
|
|
303
|
+
]
|
|
304
|
+
),
|
|
305
|
+
callback=callbacks.convert_experimental,
|
|
306
|
+
multiple=True,
|
|
307
|
+
)
|
|
308
|
+
@grouped_option(
|
|
309
|
+
"--fixups",
|
|
310
|
+
help="Applies compatibility adjustments like 'fast_api', 'utf8_bom'.",
|
|
311
|
+
multiple=True,
|
|
312
|
+
type=click.Choice(list(ALL_FIXUPS) + ["all"]),
|
|
313
|
+
)
|
|
314
|
+
@group("API validation options")
|
|
315
|
+
@grouped_option(
|
|
265
316
|
"--checks",
|
|
266
317
|
"-c",
|
|
267
318
|
multiple=True,
|
|
@@ -270,55 +321,27 @@ REPORT_TO_SERVICE = ReportToService()
|
|
|
270
321
|
f"Default is '{','.join(DEFAULT_CHECKS_NAMES)}'.",
|
|
271
322
|
type=CHECKS_TYPE,
|
|
272
323
|
default=DEFAULT_CHECKS_NAMES,
|
|
273
|
-
cls=GroupedOption,
|
|
274
|
-
group=ParameterGroup.validation,
|
|
275
324
|
callback=callbacks.convert_checks,
|
|
276
325
|
show_default=True,
|
|
277
326
|
)
|
|
278
|
-
@
|
|
327
|
+
@grouped_option(
|
|
279
328
|
"--exclude-checks",
|
|
280
329
|
multiple=True,
|
|
281
330
|
help="Specifies the validation checks to skip during testing. "
|
|
282
331
|
"Provide a comma-separated list of checks you wish to bypass.",
|
|
283
332
|
type=EXCLUDE_CHECKS_TYPE,
|
|
284
333
|
default=[],
|
|
285
|
-
cls=GroupedOption,
|
|
286
|
-
group=ParameterGroup.validation,
|
|
287
334
|
callback=callbacks.convert_checks,
|
|
288
335
|
show_default=True,
|
|
289
336
|
)
|
|
290
|
-
@
|
|
291
|
-
"--data-generation-method",
|
|
292
|
-
"-D",
|
|
293
|
-
"data_generation_methods",
|
|
294
|
-
help="Specifies the approach Schemathesis uses to generate test data. "
|
|
295
|
-
"Use 'positive' for valid data, 'negative' for invalid data, or 'all' for both. "
|
|
296
|
-
"Default is 'positive'.",
|
|
297
|
-
type=DATA_GENERATION_METHOD_TYPE,
|
|
298
|
-
default=DataGenerationMethod.default().name,
|
|
299
|
-
callback=callbacks.convert_data_generation_method,
|
|
300
|
-
show_default=True,
|
|
301
|
-
)
|
|
302
|
-
@click.option(
|
|
337
|
+
@grouped_option(
|
|
303
338
|
"--max-response-time",
|
|
304
339
|
help="Sets a custom time limit for API response times. "
|
|
305
340
|
"The test will fail if a response time exceeds this limit. "
|
|
306
341
|
"Provide the time in milliseconds.",
|
|
307
342
|
type=click.IntRange(min=1),
|
|
308
|
-
cls=GroupedOption,
|
|
309
|
-
group=ParameterGroup.validation,
|
|
310
343
|
)
|
|
311
|
-
@
|
|
312
|
-
"--target",
|
|
313
|
-
"-t",
|
|
314
|
-
"targets",
|
|
315
|
-
multiple=True,
|
|
316
|
-
help="Guides input generation to values more likely to expose bugs via targeted property-based testing.",
|
|
317
|
-
type=TARGETS_TYPE,
|
|
318
|
-
default=DEFAULT_TARGETS_NAMES,
|
|
319
|
-
show_default=True,
|
|
320
|
-
)
|
|
321
|
-
@click.option(
|
|
344
|
+
@grouped_option(
|
|
322
345
|
"-x",
|
|
323
346
|
"--exitfirst",
|
|
324
347
|
"exit_first",
|
|
@@ -327,68 +350,61 @@ REPORT_TO_SERVICE = ReportToService()
|
|
|
327
350
|
help="Terminates the test suite immediately upon the first failure or error encountered.",
|
|
328
351
|
show_default=True,
|
|
329
352
|
)
|
|
330
|
-
@
|
|
353
|
+
@grouped_option(
|
|
331
354
|
"--max-failures",
|
|
332
355
|
"max_failures",
|
|
333
356
|
type=click.IntRange(min=1),
|
|
334
357
|
help="Terminates the test suite after reaching a specified number of failures or errors.",
|
|
335
358
|
show_default=True,
|
|
336
359
|
)
|
|
337
|
-
@
|
|
338
|
-
|
|
339
|
-
"
|
|
340
|
-
|
|
341
|
-
default=False,
|
|
342
|
-
help="Simulates test execution without making any actual requests, useful for validating data generation.",
|
|
343
|
-
)
|
|
344
|
-
@click.option(
|
|
345
|
-
"--auth",
|
|
346
|
-
"-a",
|
|
347
|
-
help="Provides the server authentication details in the 'USER:PASSWORD' format.",
|
|
360
|
+
@group("Loader options")
|
|
361
|
+
@grouped_option(
|
|
362
|
+
"--app",
|
|
363
|
+
help="Specifies the WSGI/ASGI application under test, provided as an importable Python path.",
|
|
348
364
|
type=str,
|
|
349
|
-
callback=callbacks.
|
|
365
|
+
callback=callbacks.validate_app,
|
|
350
366
|
)
|
|
351
|
-
@
|
|
352
|
-
"--
|
|
353
|
-
"
|
|
354
|
-
type=click.
|
|
355
|
-
default=
|
|
356
|
-
|
|
357
|
-
show_default=True,
|
|
367
|
+
@grouped_option(
|
|
368
|
+
"--wait-for-schema",
|
|
369
|
+
help="Maximum duration, in seconds, to wait for the API schema to become available. Disabled by default.",
|
|
370
|
+
type=click.FloatRange(1.0),
|
|
371
|
+
default=None,
|
|
372
|
+
envvar=WAIT_FOR_SCHEMA_ENV_VAR,
|
|
358
373
|
)
|
|
359
|
-
@
|
|
360
|
-
"--
|
|
361
|
-
"
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
callback=callbacks.validate_set_query,
|
|
374
|
+
@grouped_option(
|
|
375
|
+
"--validate-schema",
|
|
376
|
+
help="Validates the input API schema. Set to 'true' to enable or 'false' to disable.",
|
|
377
|
+
type=bool,
|
|
378
|
+
default=False,
|
|
379
|
+
show_default=True,
|
|
366
380
|
)
|
|
367
|
-
@
|
|
368
|
-
|
|
369
|
-
"
|
|
370
|
-
|
|
371
|
-
|
|
381
|
+
@group("Network requests options")
|
|
382
|
+
@grouped_option(
|
|
383
|
+
"--base-url",
|
|
384
|
+
"-b",
|
|
385
|
+
help="Provides the base URL of the API, required when schema is provided as a file.",
|
|
372
386
|
type=str,
|
|
373
|
-
callback=callbacks.
|
|
387
|
+
callback=callbacks.validate_base_url,
|
|
388
|
+
envvar=BASE_URL_ENV_VAR,
|
|
374
389
|
)
|
|
375
|
-
@
|
|
376
|
-
"--
|
|
377
|
-
"
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
type=str,
|
|
381
|
-
callback=callbacks.validate_set_cookie,
|
|
390
|
+
@grouped_option(
|
|
391
|
+
"--request-timeout",
|
|
392
|
+
help="Sets a timeout limit, in milliseconds, for each network request during tests.",
|
|
393
|
+
type=click.IntRange(1),
|
|
394
|
+
default=DEFAULT_RESPONSE_TIMEOUT,
|
|
382
395
|
)
|
|
383
|
-
@
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
396
|
+
@with_request_proxy
|
|
397
|
+
@with_request_tls_verify
|
|
398
|
+
@with_request_cert
|
|
399
|
+
@with_request_cert_key
|
|
400
|
+
@grouped_option(
|
|
401
|
+
"--rate-limit",
|
|
402
|
+
help="Specifies a rate limit for test requests in '<limit>/<duration>' format. "
|
|
403
|
+
"Example - `100/m` for 100 requests per minute.",
|
|
388
404
|
type=str,
|
|
389
|
-
callback=callbacks.
|
|
405
|
+
callback=callbacks.validate_rate_limit,
|
|
390
406
|
)
|
|
391
|
-
@
|
|
407
|
+
@grouped_option(
|
|
392
408
|
"--header",
|
|
393
409
|
"-H",
|
|
394
410
|
"headers",
|
|
@@ -397,234 +413,188 @@ REPORT_TO_SERVICE = ReportToService()
|
|
|
397
413
|
type=str,
|
|
398
414
|
callback=callbacks.validate_headers,
|
|
399
415
|
)
|
|
416
|
+
@grouped_option(
|
|
417
|
+
"--auth",
|
|
418
|
+
"-a",
|
|
419
|
+
help="Provides the server authentication details in the 'USER:PASSWORD' format.",
|
|
420
|
+
type=str,
|
|
421
|
+
callback=callbacks.validate_auth,
|
|
422
|
+
)
|
|
423
|
+
@grouped_option(
|
|
424
|
+
"--auth-type",
|
|
425
|
+
"-A",
|
|
426
|
+
type=click.Choice(["basic", "digest"], case_sensitive=False),
|
|
427
|
+
default="basic",
|
|
428
|
+
help="Specifies the authentication method. Default is 'basic'.",
|
|
429
|
+
show_default=True,
|
|
430
|
+
)
|
|
431
|
+
@group("Filtering options")
|
|
400
432
|
@with_filters
|
|
401
|
-
@
|
|
433
|
+
@grouped_option(
|
|
402
434
|
"--include-by",
|
|
403
435
|
"include_by",
|
|
404
436
|
type=str,
|
|
405
437
|
help="Include API operations by expression",
|
|
406
|
-
cls=GroupedOption,
|
|
407
|
-
group=ParameterGroup.filtering,
|
|
408
438
|
)
|
|
409
|
-
@
|
|
439
|
+
@grouped_option(
|
|
410
440
|
"--exclude-by",
|
|
411
441
|
"exclude_by",
|
|
412
442
|
type=str,
|
|
413
443
|
help="Exclude API operations by expression",
|
|
414
|
-
cls=GroupedOption,
|
|
415
|
-
group=ParameterGroup.filtering,
|
|
416
444
|
)
|
|
417
|
-
@
|
|
445
|
+
@grouped_option(
|
|
418
446
|
"--exclude-deprecated",
|
|
419
447
|
help="Exclude deprecated API operations from testing.",
|
|
420
448
|
is_flag=True,
|
|
421
449
|
is_eager=True,
|
|
422
450
|
default=False,
|
|
423
451
|
show_default=True,
|
|
424
|
-
cls=GroupedOption,
|
|
425
|
-
group=ParameterGroup.filtering,
|
|
426
452
|
)
|
|
427
|
-
@
|
|
453
|
+
@grouped_option(
|
|
428
454
|
"--endpoint",
|
|
429
455
|
"-E",
|
|
430
456
|
"endpoints",
|
|
431
457
|
type=str,
|
|
432
458
|
multiple=True,
|
|
433
|
-
help=r"API operation path pattern (e.g., users/\d+).",
|
|
459
|
+
help=r"[DEPRECATED] API operation path pattern (e.g., users/\d+).",
|
|
434
460
|
callback=callbacks.validate_regex,
|
|
435
|
-
|
|
436
|
-
group=ParameterGroup.filtering,
|
|
461
|
+
hidden=True,
|
|
437
462
|
)
|
|
438
|
-
@
|
|
463
|
+
@grouped_option(
|
|
439
464
|
"--method",
|
|
440
465
|
"-M",
|
|
441
466
|
"methods",
|
|
442
467
|
type=str,
|
|
443
468
|
multiple=True,
|
|
444
|
-
help="HTTP method (e.g., GET, POST).",
|
|
469
|
+
help="[DEPRECATED] HTTP method (e.g., GET, POST).",
|
|
445
470
|
callback=callbacks.validate_regex,
|
|
446
|
-
|
|
447
|
-
group=ParameterGroup.filtering,
|
|
471
|
+
hidden=True,
|
|
448
472
|
)
|
|
449
|
-
@
|
|
473
|
+
@grouped_option(
|
|
450
474
|
"--tag",
|
|
451
475
|
"-T",
|
|
452
476
|
"tags",
|
|
453
477
|
type=str,
|
|
454
478
|
multiple=True,
|
|
455
|
-
help="Schema tag pattern.",
|
|
479
|
+
help="[DEPRECATED] Schema tag pattern.",
|
|
456
480
|
callback=callbacks.validate_regex,
|
|
457
|
-
|
|
458
|
-
group=ParameterGroup.filtering,
|
|
481
|
+
hidden=True,
|
|
459
482
|
)
|
|
460
|
-
@
|
|
483
|
+
@grouped_option(
|
|
461
484
|
"--operation-id",
|
|
462
485
|
"-O",
|
|
463
486
|
"operation_ids",
|
|
464
487
|
type=str,
|
|
465
488
|
multiple=True,
|
|
466
|
-
help="OpenAPI operationId pattern.",
|
|
489
|
+
help="[DEPRECATED] OpenAPI operationId pattern.",
|
|
467
490
|
callback=callbacks.validate_regex,
|
|
468
|
-
|
|
469
|
-
group=ParameterGroup.filtering,
|
|
470
|
-
)
|
|
471
|
-
@click.option(
|
|
472
|
-
"--workers",
|
|
473
|
-
"-w",
|
|
474
|
-
"workers_num",
|
|
475
|
-
help="Sets the number of concurrent workers for testing. Auto-adjusts if 'auto' is specified.",
|
|
476
|
-
type=CustomHelpMessageChoice(
|
|
477
|
-
["auto"] + list(map(str, range(MIN_WORKERS, MAX_WORKERS + 1))),
|
|
478
|
-
choices_repr=f"[auto|{MIN_WORKERS}-{MAX_WORKERS}]",
|
|
479
|
-
),
|
|
480
|
-
default=str(DEFAULT_WORKERS),
|
|
481
|
-
show_default=True,
|
|
482
|
-
callback=callbacks.convert_workers,
|
|
483
|
-
)
|
|
484
|
-
@click.option(
|
|
485
|
-
"--base-url",
|
|
486
|
-
"-b",
|
|
487
|
-
help="Provides the base URL of the API, required when schema is provided as a file.",
|
|
488
|
-
type=str,
|
|
489
|
-
callback=callbacks.validate_base_url,
|
|
490
|
-
envvar=BASE_URL_ENV_VAR,
|
|
491
|
-
)
|
|
492
|
-
@click.option(
|
|
493
|
-
"--app",
|
|
494
|
-
help="Specifies the WSGI/ASGI application under test, provided as an importable Python path.",
|
|
495
|
-
type=str,
|
|
496
|
-
callback=callbacks.validate_app,
|
|
497
|
-
)
|
|
498
|
-
@click.option(
|
|
499
|
-
"--wait-for-schema",
|
|
500
|
-
help="Maximum duration, in seconds, to wait for the API schema to become available.",
|
|
501
|
-
type=click.FloatRange(1.0),
|
|
502
|
-
default=None,
|
|
503
|
-
envvar=WAIT_FOR_SCHEMA_ENV_VAR,
|
|
504
|
-
)
|
|
505
|
-
@click.option(
|
|
506
|
-
"--request-timeout",
|
|
507
|
-
help="Sets a timeout limit, in milliseconds, for each network request during tests.",
|
|
508
|
-
type=click.IntRange(1),
|
|
509
|
-
default=DEFAULT_RESPONSE_TIMEOUT,
|
|
510
|
-
)
|
|
511
|
-
@with_request_proxy
|
|
512
|
-
@with_request_tls_verify
|
|
513
|
-
@with_request_cert
|
|
514
|
-
@with_request_cert_key
|
|
515
|
-
@click.option(
|
|
516
|
-
"--validate-schema",
|
|
517
|
-
help="Toggles validation of incoming payloads against the defined API schema. "
|
|
518
|
-
"Set to 'True' to enable or 'False' to disable. "
|
|
519
|
-
"Default is 'False'.",
|
|
520
|
-
type=bool,
|
|
521
|
-
default=False,
|
|
522
|
-
show_default=True,
|
|
523
|
-
cls=GroupedOption,
|
|
524
|
-
group=ParameterGroup.validation,
|
|
491
|
+
hidden=True,
|
|
525
492
|
)
|
|
526
|
-
@
|
|
493
|
+
@grouped_option(
|
|
527
494
|
"--skip-deprecated-operations",
|
|
528
|
-
help="Exclude deprecated API operations from testing.",
|
|
495
|
+
help="[DEPRECATED] Exclude deprecated API operations from testing.",
|
|
529
496
|
is_flag=True,
|
|
530
497
|
is_eager=True,
|
|
531
498
|
default=False,
|
|
532
499
|
show_default=True,
|
|
533
|
-
|
|
534
|
-
group=ParameterGroup.filtering,
|
|
500
|
+
hidden=True,
|
|
535
501
|
)
|
|
536
|
-
@
|
|
502
|
+
@group("Output options")
|
|
503
|
+
@grouped_option(
|
|
537
504
|
"--junit-xml",
|
|
538
505
|
help="Outputs a JUnit-XML style report at the specified file path.",
|
|
539
506
|
type=click.File("w", encoding="utf-8"),
|
|
540
507
|
)
|
|
541
|
-
@
|
|
542
|
-
"--report",
|
|
543
|
-
"report_value",
|
|
544
|
-
help="""Specifies how the generated report should be handled.
|
|
545
|
-
If used without an argument, the report data will automatically be uploaded to Schemathesis.io.
|
|
546
|
-
If a file name is provided, the report will be stored in that file.
|
|
547
|
-
The report data, consisting of a tar gz file with multiple JSON files, is subject to change.""",
|
|
548
|
-
is_flag=False,
|
|
549
|
-
flag_value="",
|
|
550
|
-
envvar=service.REPORT_ENV_VAR,
|
|
551
|
-
callback=callbacks.convert_report, # type: ignore
|
|
552
|
-
)
|
|
553
|
-
@click.option(
|
|
554
|
-
"--debug-output-file",
|
|
555
|
-
help="Saves debugging information in a JSONL format at the specified file path.",
|
|
556
|
-
type=click.File("w", encoding="utf-8"),
|
|
557
|
-
)
|
|
558
|
-
@click.option(
|
|
559
|
-
"--show-errors-tracebacks",
|
|
560
|
-
help="Displays complete traceback information for internal errors.",
|
|
561
|
-
is_flag=True,
|
|
562
|
-
is_eager=True,
|
|
563
|
-
default=False,
|
|
564
|
-
hidden=True,
|
|
565
|
-
show_default=True,
|
|
566
|
-
)
|
|
567
|
-
@click.option(
|
|
568
|
-
"--show-trace",
|
|
569
|
-
help="Displays complete traceback information for internal errors.",
|
|
570
|
-
is_flag=True,
|
|
571
|
-
is_eager=True,
|
|
572
|
-
default=False,
|
|
573
|
-
show_default=True,
|
|
574
|
-
)
|
|
575
|
-
@click.option(
|
|
576
|
-
"--code-sample-style",
|
|
577
|
-
help="Selects the code sample style for reproducing failures.",
|
|
578
|
-
type=click.Choice([item.name for item in CodeSampleStyle]),
|
|
579
|
-
default=CodeSampleStyle.default().name,
|
|
580
|
-
callback=callbacks.convert_code_sample_style,
|
|
581
|
-
)
|
|
582
|
-
@click.option(
|
|
508
|
+
@grouped_option(
|
|
583
509
|
"--cassette-path",
|
|
584
510
|
help="Saves the test outcomes in a VCR-compatible format.",
|
|
585
511
|
type=click.File("w", encoding="utf-8"),
|
|
586
512
|
is_eager=True,
|
|
587
513
|
)
|
|
588
|
-
@
|
|
514
|
+
@grouped_option(
|
|
589
515
|
"--cassette-format",
|
|
590
516
|
help="Format of the saved cassettes.",
|
|
591
517
|
type=click.Choice([item.name.lower() for item in cassettes.CassetteFormat]),
|
|
592
518
|
default=cassettes.CassetteFormat.VCR.name.lower(),
|
|
593
519
|
callback=callbacks.convert_cassette_format,
|
|
594
520
|
)
|
|
595
|
-
@
|
|
521
|
+
@grouped_option(
|
|
596
522
|
"--cassette-preserve-exact-body-bytes",
|
|
597
523
|
help="Retains exact byte sequence of payloads in cassettes, encoded as base64.",
|
|
598
524
|
is_flag=True,
|
|
599
525
|
callback=callbacks.validate_preserve_exact_body_bytes,
|
|
600
526
|
)
|
|
601
|
-
@
|
|
527
|
+
@grouped_option(
|
|
528
|
+
"--code-sample-style",
|
|
529
|
+
help="Selects the code sample style for reproducing failures.",
|
|
530
|
+
type=click.Choice([item.name for item in CodeSampleStyle]),
|
|
531
|
+
default=CodeSampleStyle.default().name,
|
|
532
|
+
callback=callbacks.convert_code_sample_style,
|
|
533
|
+
)
|
|
534
|
+
@grouped_option(
|
|
535
|
+
"--sanitize-output",
|
|
536
|
+
type=bool,
|
|
537
|
+
default=True,
|
|
538
|
+
show_default=True,
|
|
539
|
+
help="Enable or disable automatic output sanitization to obscure sensitive data.",
|
|
540
|
+
)
|
|
541
|
+
@grouped_option(
|
|
542
|
+
"--output-truncate",
|
|
543
|
+
help="Specifies whether to truncate schemas and responses in error messages.",
|
|
544
|
+
type=str,
|
|
545
|
+
default="true",
|
|
546
|
+
show_default=True,
|
|
547
|
+
callback=callbacks.convert_boolean_string,
|
|
548
|
+
)
|
|
549
|
+
@grouped_option(
|
|
550
|
+
"--show-trace",
|
|
551
|
+
help="Displays complete traceback information for internal errors.",
|
|
552
|
+
is_flag=True,
|
|
553
|
+
is_eager=True,
|
|
554
|
+
default=False,
|
|
555
|
+
show_default=True,
|
|
556
|
+
)
|
|
557
|
+
@grouped_option(
|
|
558
|
+
"--debug-output-file",
|
|
559
|
+
help="Saves debugging information in a JSONL format at the specified file path.",
|
|
560
|
+
type=click.File("w", encoding="utf-8"),
|
|
561
|
+
)
|
|
562
|
+
@grouped_option(
|
|
602
563
|
"--store-network-log",
|
|
603
|
-
help="Saves the test outcomes in a VCR-compatible format.",
|
|
564
|
+
help="[DEPRECATED] Saves the test outcomes in a VCR-compatible format.",
|
|
604
565
|
type=click.File("w", encoding="utf-8"),
|
|
605
566
|
hidden=True,
|
|
606
567
|
)
|
|
607
|
-
@
|
|
608
|
-
"--
|
|
609
|
-
help="
|
|
610
|
-
|
|
611
|
-
|
|
568
|
+
@grouped_option(
|
|
569
|
+
"--show-errors-tracebacks",
|
|
570
|
+
help="[DEPRECATED] Displays complete traceback information for internal errors.",
|
|
571
|
+
is_flag=True,
|
|
572
|
+
is_eager=True,
|
|
573
|
+
default=False,
|
|
574
|
+
hidden=True,
|
|
575
|
+
show_default=True,
|
|
612
576
|
)
|
|
613
|
-
@
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
"
|
|
617
|
-
|
|
618
|
-
|
|
577
|
+
@group("Data generation options")
|
|
578
|
+
@grouped_option(
|
|
579
|
+
"--data-generation-method",
|
|
580
|
+
"-D",
|
|
581
|
+
"data_generation_methods",
|
|
582
|
+
help="Specifies the approach Schemathesis uses to generate test data. "
|
|
583
|
+
"Use 'positive' for valid data, 'negative' for invalid data, or 'all' for both. "
|
|
584
|
+
"Default is 'positive'.",
|
|
585
|
+
type=DATA_GENERATION_METHOD_TYPE,
|
|
586
|
+
default=DataGenerationMethod.default().name,
|
|
587
|
+
callback=callbacks.convert_data_generation_method,
|
|
588
|
+
show_default=True,
|
|
619
589
|
)
|
|
620
|
-
@
|
|
590
|
+
@grouped_option(
|
|
621
591
|
"--stateful",
|
|
622
|
-
help="Enables or disables stateful testing
|
|
592
|
+
help="Enables or disables stateful testing.",
|
|
623
593
|
type=click.Choice([item.name for item in Stateful]),
|
|
624
594
|
default=Stateful.links.name,
|
|
625
595
|
callback=callbacks.convert_stateful,
|
|
626
596
|
)
|
|
627
|
-
@
|
|
597
|
+
@grouped_option(
|
|
628
598
|
"--stateful-recursion-limit",
|
|
629
599
|
help="Sets the recursion depth limit for stateful testing.",
|
|
630
600
|
default=DEFAULT_STATEFUL_RECURSION_LIMIT,
|
|
@@ -632,19 +602,38 @@ The report data, consisting of a tar gz file with multiple JSON files, is subjec
|
|
|
632
602
|
type=click.IntRange(1, 100),
|
|
633
603
|
hidden=True,
|
|
634
604
|
)
|
|
635
|
-
@
|
|
636
|
-
"--
|
|
637
|
-
help="
|
|
638
|
-
type=
|
|
605
|
+
@grouped_option(
|
|
606
|
+
"--generation-allow-x00",
|
|
607
|
+
help="Determines whether to allow the generation of `\x00` bytes within strings.",
|
|
608
|
+
type=str,
|
|
609
|
+
default="true",
|
|
610
|
+
show_default=True,
|
|
611
|
+
callback=callbacks.convert_boolean_string,
|
|
639
612
|
)
|
|
640
|
-
@
|
|
641
|
-
"--
|
|
642
|
-
|
|
643
|
-
|
|
613
|
+
@grouped_option(
|
|
614
|
+
"--generation-codec",
|
|
615
|
+
help="Specifies the codec used for generating strings.",
|
|
616
|
+
type=str,
|
|
617
|
+
default="utf-8",
|
|
618
|
+
callback=callbacks.validate_generation_codec,
|
|
619
|
+
)
|
|
620
|
+
@grouped_option(
|
|
621
|
+
"--generation-with-security-parameters",
|
|
622
|
+
help="Whether to generate security parameters.",
|
|
623
|
+
type=str,
|
|
624
|
+
default="true",
|
|
644
625
|
show_default=True,
|
|
645
|
-
|
|
626
|
+
callback=callbacks.convert_boolean_string,
|
|
646
627
|
)
|
|
647
|
-
@
|
|
628
|
+
@grouped_option(
|
|
629
|
+
"--generation-graphql-allow-null",
|
|
630
|
+
help="Whether `null` values should be used for optional arguments in GraphQL queries.",
|
|
631
|
+
type=str,
|
|
632
|
+
default="true",
|
|
633
|
+
show_default=True,
|
|
634
|
+
callback=callbacks.convert_boolean_string,
|
|
635
|
+
)
|
|
636
|
+
@grouped_option(
|
|
648
637
|
"--contrib-unique-data",
|
|
649
638
|
"contrib_unique_data",
|
|
650
639
|
help="Forces the generation of unique test cases.",
|
|
@@ -652,7 +641,7 @@ The report data, consisting of a tar gz file with multiple JSON files, is subjec
|
|
|
652
641
|
default=False,
|
|
653
642
|
show_default=True,
|
|
654
643
|
)
|
|
655
|
-
@
|
|
644
|
+
@grouped_option(
|
|
656
645
|
"--contrib-openapi-formats-uuid",
|
|
657
646
|
"contrib_openapi_formats_uuid",
|
|
658
647
|
help="Enables support for the 'uuid' string format in OpenAPI.",
|
|
@@ -660,7 +649,7 @@ The report data, consisting of a tar gz file with multiple JSON files, is subjec
|
|
|
660
649
|
default=False,
|
|
661
650
|
show_default=True,
|
|
662
651
|
)
|
|
663
|
-
@
|
|
652
|
+
@grouped_option(
|
|
664
653
|
"--contrib-openapi-fill-missing-examples",
|
|
665
654
|
"contrib_openapi_fill_missing_examples",
|
|
666
655
|
help="Enables generation of random examples for API operations that do not have explicit examples defined.",
|
|
@@ -668,157 +657,141 @@ The report data, consisting of a tar gz file with multiple JSON files, is subjec
|
|
|
668
657
|
default=False,
|
|
669
658
|
show_default=True,
|
|
670
659
|
)
|
|
671
|
-
@
|
|
660
|
+
@grouped_option(
|
|
661
|
+
"--target",
|
|
662
|
+
"-t",
|
|
663
|
+
"targets",
|
|
664
|
+
multiple=True,
|
|
665
|
+
help="Guides input generation to values more likely to expose bugs via targeted property-based testing.",
|
|
666
|
+
type=TARGETS_TYPE,
|
|
667
|
+
default=DEFAULT_TARGETS_NAMES,
|
|
668
|
+
show_default=True,
|
|
669
|
+
)
|
|
670
|
+
@group("Open API options")
|
|
671
|
+
@grouped_option(
|
|
672
|
+
"--force-schema-version",
|
|
673
|
+
help="Forces the schema to be interpreted as a particular OpenAPI version.",
|
|
674
|
+
type=click.Choice(["20", "30"]),
|
|
675
|
+
)
|
|
676
|
+
@grouped_option(
|
|
677
|
+
"--set-query",
|
|
678
|
+
"set_query",
|
|
679
|
+
help=r"OpenAPI: Override a specific query parameter by specifying 'parameter=value'",
|
|
680
|
+
multiple=True,
|
|
681
|
+
type=str,
|
|
682
|
+
callback=callbacks.validate_set_query,
|
|
683
|
+
)
|
|
684
|
+
@grouped_option(
|
|
685
|
+
"--set-header",
|
|
686
|
+
"set_header",
|
|
687
|
+
help=r"OpenAPI: Override a specific header parameter by specifying 'parameter=value'",
|
|
688
|
+
multiple=True,
|
|
689
|
+
type=str,
|
|
690
|
+
callback=callbacks.validate_set_header,
|
|
691
|
+
)
|
|
692
|
+
@grouped_option(
|
|
693
|
+
"--set-cookie",
|
|
694
|
+
"set_cookie",
|
|
695
|
+
help=r"OpenAPI: Override a specific cookie parameter by specifying 'parameter=value'",
|
|
696
|
+
multiple=True,
|
|
697
|
+
type=str,
|
|
698
|
+
callback=callbacks.validate_set_cookie,
|
|
699
|
+
)
|
|
700
|
+
@grouped_option(
|
|
701
|
+
"--set-path",
|
|
702
|
+
"set_path",
|
|
703
|
+
help=r"OpenAPI: Override a specific path parameter by specifying 'parameter=value'",
|
|
704
|
+
multiple=True,
|
|
705
|
+
type=str,
|
|
706
|
+
callback=callbacks.validate_set_path,
|
|
707
|
+
)
|
|
708
|
+
@group("Hypothesis engine options")
|
|
709
|
+
@grouped_option(
|
|
672
710
|
"--hypothesis-database",
|
|
673
711
|
help="Configures storage for examples discovered by Hypothesis. "
|
|
674
712
|
f"Use 'none' to disable, '{HYPOTHESIS_IN_MEMORY_DATABASE_IDENTIFIER}' for temporary storage, "
|
|
675
713
|
f"or specify a file path for persistent storage.",
|
|
676
714
|
type=str,
|
|
677
|
-
cls=GroupedOption,
|
|
678
|
-
group=ParameterGroup.hypothesis,
|
|
679
715
|
callback=callbacks.validate_hypothesis_database,
|
|
680
716
|
)
|
|
681
|
-
@
|
|
717
|
+
@grouped_option(
|
|
682
718
|
"--hypothesis-deadline",
|
|
683
719
|
help="Sets a time limit for each test case generated by Hypothesis, in milliseconds. "
|
|
684
720
|
"Exceeding this limit will cause the test to fail.",
|
|
685
|
-
|
|
686
|
-
type=OptionalInt(1, 999999999 * 24 * 3600 * 1000),
|
|
687
|
-
cls=GroupedOption,
|
|
688
|
-
group=ParameterGroup.hypothesis,
|
|
721
|
+
type=OptionalInt(1, 5 * 60 * 1000),
|
|
689
722
|
)
|
|
690
|
-
@
|
|
723
|
+
@grouped_option(
|
|
691
724
|
"--hypothesis-derandomize",
|
|
692
725
|
help="Enables deterministic mode in Hypothesis, which eliminates random variation between test runs.",
|
|
693
726
|
is_flag=True,
|
|
694
727
|
is_eager=True,
|
|
695
728
|
default=None,
|
|
696
729
|
show_default=True,
|
|
697
|
-
cls=GroupedOption,
|
|
698
|
-
group=ParameterGroup.hypothesis,
|
|
699
730
|
)
|
|
700
|
-
@
|
|
731
|
+
@grouped_option(
|
|
701
732
|
"--hypothesis-max-examples",
|
|
702
733
|
help="Sets the cap on the number of examples generated by Hypothesis for each API method/path pair.",
|
|
703
734
|
type=click.IntRange(1),
|
|
704
|
-
cls=GroupedOption,
|
|
705
|
-
group=ParameterGroup.hypothesis,
|
|
706
735
|
)
|
|
707
|
-
@
|
|
736
|
+
@grouped_option(
|
|
708
737
|
"--hypothesis-phases",
|
|
709
738
|
help="Specifies which testing phases to execute.",
|
|
710
739
|
type=CsvEnumChoice(Phase),
|
|
711
|
-
cls=GroupedOption,
|
|
712
|
-
group=ParameterGroup.hypothesis,
|
|
713
740
|
)
|
|
714
|
-
@
|
|
741
|
+
@grouped_option(
|
|
715
742
|
"--hypothesis-no-phases",
|
|
716
743
|
help="Specifies which testing phases to exclude from execution.",
|
|
717
744
|
type=CsvEnumChoice(Phase),
|
|
718
|
-
cls=GroupedOption,
|
|
719
|
-
group=ParameterGroup.hypothesis,
|
|
720
745
|
)
|
|
721
|
-
@
|
|
746
|
+
@grouped_option(
|
|
722
747
|
"--hypothesis-report-multiple-bugs",
|
|
723
748
|
help="If set, only the most easily reproducible exception will be reported when multiple issues are found.",
|
|
724
749
|
type=bool,
|
|
725
|
-
cls=GroupedOption,
|
|
726
|
-
group=ParameterGroup.hypothesis,
|
|
727
750
|
)
|
|
728
|
-
@
|
|
751
|
+
@grouped_option(
|
|
729
752
|
"--hypothesis-seed",
|
|
730
753
|
help="Sets a seed value for Hypothesis, ensuring reproducibility across test runs.",
|
|
731
754
|
type=int,
|
|
732
|
-
cls=GroupedOption,
|
|
733
|
-
group=ParameterGroup.hypothesis,
|
|
734
755
|
)
|
|
735
|
-
@
|
|
756
|
+
@grouped_option(
|
|
736
757
|
"--hypothesis-suppress-health-check",
|
|
737
758
|
help="Disables specified health checks from Hypothesis like 'data_too_large', 'filter_too_much', etc. "
|
|
738
759
|
"Provide a comma-separated list",
|
|
739
760
|
type=CsvEnumChoice(HealthCheck),
|
|
740
|
-
cls=GroupedOption,
|
|
741
|
-
group=ParameterGroup.hypothesis,
|
|
742
761
|
)
|
|
743
|
-
@
|
|
762
|
+
@grouped_option(
|
|
744
763
|
"--hypothesis-verbosity",
|
|
745
764
|
help="Controls the verbosity level of Hypothesis output.",
|
|
746
765
|
type=click.Choice([item.name for item in Verbosity]),
|
|
747
766
|
callback=callbacks.convert_verbosity,
|
|
748
|
-
cls=GroupedOption,
|
|
749
|
-
group=ParameterGroup.hypothesis,
|
|
750
|
-
)
|
|
751
|
-
@click.option("--no-color", help="Disable ANSI color escape codes.", type=bool, is_flag=True)
|
|
752
|
-
@click.option("--force-color", help="Explicitly tells to enable ANSI color escape codes.", type=bool, is_flag=True)
|
|
753
|
-
@click.option(
|
|
754
|
-
"--experimental",
|
|
755
|
-
"experiments",
|
|
756
|
-
help="Enable experimental support for specific features.",
|
|
757
|
-
type=click.Choice(
|
|
758
|
-
[
|
|
759
|
-
experimental.OPEN_API_3_1.name,
|
|
760
|
-
experimental.SCHEMA_ANALYSIS.name,
|
|
761
|
-
experimental.STATEFUL_TEST_RUNNER.name,
|
|
762
|
-
experimental.STATEFUL_ONLY.name,
|
|
763
|
-
experimental.COVERAGE_PHASE.name,
|
|
764
|
-
]
|
|
765
|
-
),
|
|
766
|
-
callback=callbacks.convert_experimental,
|
|
767
|
-
multiple=True,
|
|
768
|
-
)
|
|
769
|
-
@click.option(
|
|
770
|
-
"--output-truncate",
|
|
771
|
-
help="Specifies whether to truncate schemas and responses in error messages.",
|
|
772
|
-
type=str,
|
|
773
|
-
default="true",
|
|
774
|
-
show_default=True,
|
|
775
|
-
callback=callbacks.convert_boolean_string,
|
|
776
767
|
)
|
|
777
|
-
@
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
"
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
default="utf-8",
|
|
790
|
-
callback=callbacks.validate_generation_codec,
|
|
791
|
-
)
|
|
792
|
-
@click.option(
|
|
793
|
-
"--generation-with-security-parameters",
|
|
794
|
-
help="Whether to generate security parameters.",
|
|
795
|
-
type=str,
|
|
796
|
-
default="true",
|
|
797
|
-
show_default=True,
|
|
798
|
-
callback=callbacks.convert_boolean_string,
|
|
799
|
-
)
|
|
800
|
-
@click.option(
|
|
801
|
-
"--generation-graphql-allow-null",
|
|
802
|
-
help="Whether `null` values should be used for optional arguments in GraphQL queries.",
|
|
803
|
-
type=str,
|
|
804
|
-
default="true",
|
|
805
|
-
show_default=True,
|
|
806
|
-
callback=callbacks.convert_boolean_string,
|
|
768
|
+
@group("Schemathesis.io options")
|
|
769
|
+
@grouped_option(
|
|
770
|
+
"--report",
|
|
771
|
+
"report_value",
|
|
772
|
+
help="""Specifies how the generated report should be handled.
|
|
773
|
+
If used without an argument, the report data will automatically be uploaded to Schemathesis.io.
|
|
774
|
+
If a file name is provided, the report will be stored in that file.
|
|
775
|
+
The report data, consisting of a tar gz file with multiple JSON files, is subject to change.""",
|
|
776
|
+
is_flag=False,
|
|
777
|
+
flag_value="",
|
|
778
|
+
envvar=service.REPORT_ENV_VAR,
|
|
779
|
+
callback=callbacks.convert_report, # type: ignore
|
|
807
780
|
)
|
|
808
|
-
@
|
|
781
|
+
@grouped_option(
|
|
809
782
|
"--schemathesis-io-token",
|
|
810
783
|
help="Schemathesis.io authentication token.",
|
|
811
784
|
type=str,
|
|
812
785
|
envvar=service.TOKEN_ENV_VAR,
|
|
813
786
|
)
|
|
814
|
-
@
|
|
787
|
+
@grouped_option(
|
|
815
788
|
"--schemathesis-io-url",
|
|
816
789
|
help="Schemathesis.io base URL.",
|
|
817
790
|
default=service.DEFAULT_URL,
|
|
818
791
|
type=str,
|
|
819
792
|
envvar=service.URL_ENV_VAR,
|
|
820
793
|
)
|
|
821
|
-
@
|
|
794
|
+
@grouped_option(
|
|
822
795
|
"--schemathesis-io-telemetry",
|
|
823
796
|
help="Controls whether you send anonymized CLI usage data to Schemathesis.io along with your report.",
|
|
824
797
|
type=str,
|
|
@@ -828,7 +801,10 @@ The report data, consisting of a tar gz file with multiple JSON files, is subjec
|
|
|
828
801
|
envvar=service.TELEMETRY_ENV_VAR,
|
|
829
802
|
)
|
|
830
803
|
@with_hosts_file
|
|
831
|
-
@
|
|
804
|
+
@group("Global options")
|
|
805
|
+
@grouped_option("--verbosity", "-v", help="Increase verbosity of the output.", count=True)
|
|
806
|
+
@grouped_option("--no-color", help="Disable ANSI color escape codes.", type=bool, is_flag=True)
|
|
807
|
+
@grouped_option("--force-color", help="Explicitly tells to enable ANSI color escape codes.", type=bool, is_flag=True)
|
|
832
808
|
@click.pass_context
|
|
833
809
|
def run(
|
|
834
810
|
ctx: click.Context,
|
|
@@ -2012,6 +1988,25 @@ def add_option(*args: Any, cls: Type = click.Option, **kwargs: Any) -> None:
|
|
|
2012
1988
|
run.params.append(cls(args, **kwargs))
|
|
2013
1989
|
|
|
2014
1990
|
|
|
1991
|
+
@dataclass
|
|
1992
|
+
class Group:
|
|
1993
|
+
name: str
|
|
1994
|
+
|
|
1995
|
+
def add_option(self, *args: Any, **kwargs: Any) -> None:
|
|
1996
|
+
kwargs["cls"] = GroupedOption
|
|
1997
|
+
kwargs["group"] = self.name
|
|
1998
|
+
add_option(*args, **kwargs)
|
|
1999
|
+
|
|
2000
|
+
|
|
2001
|
+
def add_group(name: str, *, index: int | None = None) -> Group:
|
|
2002
|
+
"""Add a custom options group to `st run`."""
|
|
2003
|
+
if index is not None:
|
|
2004
|
+
GROUPS.insert(index, name)
|
|
2005
|
+
else:
|
|
2006
|
+
GROUPS.append(name)
|
|
2007
|
+
return Group(name)
|
|
2008
|
+
|
|
2009
|
+
|
|
2015
2010
|
def handler() -> Callable[[Type], None]:
|
|
2016
2011
|
"""Register a new CLI event handler."""
|
|
2017
2012
|
|