def test_url_joining(request, server, get_schema_path, schema_path): if schema_path == "petstore_v2.yaml": base_url = request.getfixturevalue("openapi2_base_url") else: base_url = request.getfixturevalue("openapi3_base_url") path = get_schema_path(schema_path) schema = oas_loaders.from_path(path, base_url=f"{base_url}/v3", endpoint="/pet/findByStatus") *_, after_execution, _ = from_schema(schema, hypothesis_settings=hypothesis.settings(max_examples=1)).execute() assert after_execution.result.path == "/api/v3/pet/findByStatus" assert ( f"http://127.0.0.1:{server['port']}/api/v3/pet/findByStatus" in after_execution.result.checks[0].example.requests_code )
def test_number_deserializing(testdir): # When numbers in a schema are written in scientific notation but without a dot # (achieved by dumping the schema with json.dumps) schema = { "openapi": "3.0.2", "info": { "title": "Test", "description": "Test", "version": "0.1.0" }, "paths": { "/teapot": { "get": { "summary": "Test", "parameters": [{ "name": "key", "in": "query", "required": True, "schema": { "type": "number", "multipleOf": 0.00001 }, }], "responses": { "200": { "description": "OK" } }, } } }, } schema_path = testdir.makefile(".yaml", schema=json.dumps(schema)) # Then yaml loader should parse them without schema validation errors parsed = loaders.from_path(str(schema_path)) # and the value should be a number value = parsed.raw_schema["paths"]["/teapot"]["get"]["parameters"][0][ "schema"]["multipleOf"] assert isinstance(value, float)
def test_runner(schema_path): schema = loaders.from_path(schema_path, validate_schema=False) runner = from_schema( schema, dry_run=True, count_operations=False, hypothesis_settings=hypothesis.settings( max_examples=1, suppress_health_check=HealthCheck.all(), phases=[Phase.explicit, Phase.generate] ), ) schema_id = get_id(schema_path) def check_xfailed(ev) -> bool: if schema_id in XFAILING and ev.current_operation in XFAILING[schema_id]: if ev.result.errors: message = XFAILING[schema_id][ev.current_operation] # If is is failed for some other reason, then an assertion will be risen return any(message in err.exception_with_traceback for err in ev.result.errors) pytest.fail("Expected a failure") return False def is_unsatisfiable(text): return "Unable to satisfy schema parameters for this API operation" in text def check_flaky(ev) -> bool: if schema_id in FLAKY_SCHEMAS and ev.current_operation in FLAKY_SCHEMAS[schema_id]: if ev.result.errors: # NOTE. There could be other errors if the "Unsatisfiable" case wasn't triggered. # Could be added to expected errors later return any(is_unsatisfiable(err.exception_with_traceback) for err in ev.result.errors) return False def check_unsatisfiable(ev): # In some cases Schemathesis can't generate data - either due to a contradiction within the schema if schema_id in UNSATISFIABLE_SCHEMAS and ev.current_operation in UNSATISFIABLE_SCHEMAS[schema_id]: exception = ev.result.errors[0].exception if ( "Unable to satisfy schema parameters for this API operation" not in exception and "Cannot create non-empty lists with elements" not in exception and "Cannot create a collection of " not in exception ): pytest.fail(f"Expected unsatisfiable, but there is a different error: {exception}") return True return False def check_recursive_references(ev): if schema_id in RECURSIVE_REFERENCES and ev.current_operation in RECURSIVE_REFERENCES[schema_id]: for err in ev.result.errors: if RECURSIVE_REFERENCE_ERROR_MESSAGE in err.exception_with_traceback: # It is OK return True # These errors may be triggered not every time return False def check_not_parsable(ev): return schema_id in NOT_PARSABLE_SCHEMAS and NOT_PARSABLE_SCHEMAS[schema_id] in ev.exception_with_traceback def check_invalid(ev): if schema_id in INVALID_SCHEMAS: if ev.result.errors: return any( "The API schema contains non-string keys" in err.exception_with_traceback for err in ev.result.errors ) return pytest.fail("Expected YAML parsing error") return False for event in runner.execute(): if isinstance(event, events.AfterExecution): if check_xfailed(event): continue if check_flaky(event): continue if check_recursive_references(event): continue if check_unsatisfiable(event): continue if check_invalid(event): continue assert not event.result.has_errors, event.current_operation assert not event.result.has_failures, event.current_operation if isinstance(event, events.InternalError): if check_not_parsable(event): continue assert not isinstance(event, events.InternalError), event.exception_with_traceback