diff --git a/openapi_spec_validator/__main__.py b/openapi_spec_validator/__main__.py index eb2884a..19abb60 100644 --- a/openapi_spec_validator/__main__.py +++ b/openapi_spec_validator/__main__.py @@ -2,6 +2,8 @@ import argparse import sys +from jsonschema.exceptions import best_match + from openapi_spec_validator import ( openapi_v2_spec_validator, openapi_v3_spec_validator, ) @@ -15,9 +17,37 @@ ) +def print_validationerror(exc, errors="best-match"): + print("# Validation Error\n") + print(exc) + if exc.cause: + print("\n# Cause\n") + print(exc.cause) + if not exc.context: + return + if errors == "all": + print("\n\n# Due to one of those errors\n") + print("\n\n\n".join("## " + str(e) for e in exc.context)) + elif errors == "best-match": + print("\n\n# Probably due to this subschema error\n") + print("## " + str(best_match(exc.context))) + if len(exc.context) > 1: + print( + "\n({} more subschemas errors,".format(len(exc.context) - 1), + "use --errors=all to see them.)", + ) + + def main(args=None): parser = argparse.ArgumentParser() parser.add_argument('filename', help="Absolute or relative path to file") + parser.add_argument( + "--errors", + choices=("best-match", "all"), + default="best-match", + help="""Control error reporting. Defaults to "best-match", """ + """use "all" to get all subschema errors.""", + ) parser.add_argument( '--schema', help="OpenAPI schema (default: 3.0.0)", @@ -50,7 +80,7 @@ def main(args=None): try: validator.validate(spec, spec_url=spec_url) except ValidationError as exc: - print(exc) + print_validationerror(exc, args.errors) sys.exit(1) except Exception as exc: print(exc) diff --git a/tests/integration/data/v3.0/missing-description.yaml b/tests/integration/data/v3.0/missing-description.yaml new file mode 100644 index 0000000..0fe1052 --- /dev/null +++ b/tests/integration/data/v3.0/missing-description.yaml @@ -0,0 +1,18 @@ +--- +openapi: 3.0.0 + +info: + title: test + description: test + version: 0.0.1 + +paths: + "/": + get: + description: Get the API root + responses: + 200: + content: + application/json: + schema: + type: string diff --git a/tests/integration/test_main.py b/tests/integration/test_main.py index bbc1e1f..bfd5be9 100644 --- a/tests/integration/test_main.py +++ b/tests/integration/test_main.py @@ -26,6 +26,33 @@ def test_schema_v2(): main(testargs) +def test_errors_on_missing_description_best(capsys): + """An error is obviously printed given an empty schema.""" + testargs = ['./tests/integration/data/v3.0/missing-description.yaml'] + with pytest.raises(SystemExit): + main(testargs) + out, err = capsys.readouterr() + assert "Failed validating" in out + assert "'description' is a required property" in out + assert "'$ref' is a required property" not in out + assert '1 more subschemas errors' in out + + +def test_errors_on_missing_description_full(capsys): + """An error is obviously printed given an empty schema.""" + testargs = [ + "./tests/integration/data/v3.0/missing-description.yaml", + "--errors=all" + ] + with pytest.raises(SystemExit): + main(testargs) + out, err = capsys.readouterr() + assert "Failed validating" in out + assert "'description' is a required property" in out + assert "'$ref' is a required property" in out + assert '1 more subschema error' not in out + + def test_schema_unknown(): """Errors on running with unknown schema.""" testargs = ['--schema', 'x.x',