Skip to content

Commit

Permalink
fix: Use the same correlation_id in BeforeExecution and `AfterExe…
Browse files Browse the repository at this point in the history
…cution` events if the API schema contains an error that causes an `InvalidSchema` exception during test execution.
  • Loading branch information
Stranger6667 committed Feb 14, 2022
1 parent a84fe70 commit f9ac0e2
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 10 deletions.
5 changes: 5 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ Changelog
`Unreleased`_ - TBD
-------------------

**Fixed**

- Use the same ``correlation_id`` in ``BeforeExecution`` and ``AfterExecution`` events if the API schema contains an error that
causes an ``InvalidSchema`` exception during test execution.

`3.13.1`_ - 2022-02-10
----------------------

Expand Down
19 changes: 11 additions & 8 deletions src/schemathesis/runner/impl/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,8 @@ def _run_tests(
feedback = Feedback(self.stateful, operation)
# Track whether `BeforeExecution` was already emitted.
# Schema error may happen before / after `BeforeExecution`, but it should be emitted only once
before_execution_emitted = False
# and the `AfterExecution` event should have the same correlation id as previous `BeforeExecution`
before_execution_correlation_id = None
try:
for event in run_test(
operation,
Expand All @@ -143,7 +144,7 @@ def _run_tests(
):
yield event
if isinstance(event, events.BeforeExecution):
before_execution_emitted = True
before_execution_correlation_id = event.correlation_id
if isinstance(event, events.Interrupted):
return
# Additional tests, generated via the `feedback` instance
Expand All @@ -162,7 +163,7 @@ def _run_tests(
results,
data_generation_method,
recursion_level,
emit_before_execution=not before_execution_emitted,
before_execution_correlation_id=before_execution_correlation_id,
)
else:
# Schema errors
Expand Down Expand Up @@ -204,7 +205,7 @@ def handle_schema_error(
data_generation_method: DataGenerationMethod,
recursion_level: int,
*,
emit_before_execution: bool = True,
before_execution_correlation_id: Optional[str] = None,
) -> Generator[events.ExecutionEvent, None, None]:
if error.method is not None:
assert error.path is not None
Expand All @@ -218,9 +219,11 @@ def handle_schema_error(
data_generation_method=data_generation_method,
)
result.add_error(error)
correlation_id = uuid.uuid4().hex
# It might be already emitted
if emit_before_execution:
# It might be already emitted - reuse its correlation id
if before_execution_correlation_id is not None:
correlation_id = before_execution_correlation_id
else:
correlation_id = uuid.uuid4().hex
yield events.BeforeExecution(
method=method,
path=error.full_path,
Expand All @@ -244,7 +247,7 @@ def handle_schema_error(
)
results.append(result)
else:
# When there is no `method`, then the schema error may cover multiple operations and we can't display it in
# When there is no `method`, then the schema error may cover multiple operations, and we can't display it in
# the progress bar
results.generic_errors.append(error)

Expand Down
15 changes: 13 additions & 2 deletions test/cli/test_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -1997,13 +1997,20 @@ def test_get_exit_code(swagger_20, capsys):


@pytest.mark.parametrize("location", ("path", "query", "header", "cookie"))
def test_missing_content_and_schema(cli, testdir, empty_open_api_3_schema, location):
def test_missing_content_and_schema(cli, tmp_path, testdir, empty_open_api_3_schema, location):
debug_file = tmp_path / "debug.jsonl"
# When an Open API 3 parameter is missing `schema` & `content`
empty_open_api_3_schema["paths"] = {
"/foo": {"get": {"parameters": [{"in": location, "name": "X-Foo", "required": True}]}}
}
schema_file = testdir.makefile(".json", schema=json.dumps(empty_open_api_3_schema))
result = cli.run(str(schema_file), "--dry-run", "--validate-schema=false", "--hypothesis-max-examples=1")
result = cli.run(
str(schema_file),
f"--debug-output-file={debug_file}",
"--dry-run",
"--validate-schema=false",
"--hypothesis-max-examples=1",
)
lines = result.stdout.split("\n")
# Then CLI should show that this API operation errored
assert lines[10].startswith("GET /foo E")
Expand All @@ -2013,3 +2020,7 @@ def test_missing_content_and_schema(cli, testdir, empty_open_api_3_schema, locat
lines[14] == f'InvalidSchema: Can not generate data for {location} parameter "X-Foo"! '
"It should have either `schema` or `content` keywords defined"
)
# And emitted Before / After event pairs have the same correlation ids
with debug_file.open(encoding="utf-8") as fd:
events = [json.loads(line) for line in fd]
assert events[1]["correlation_id"] == events[2]["correlation_id"]

0 comments on commit f9ac0e2

Please sign in to comment.