def test_invalid_content_type(httpserver, without_content_type): # When the user tries to load an HTML as a schema content = """ <html> <style> html { margin: 0; background: #fafafa; } </style> <html> """ response = Response(response=content) if without_content_type: del response.headers["Content-Type"] path = "/openapi/" handler = httpserver.expect_request(path) handler.respond_with_response(response) schema_url = httpserver.url_for(path) # And loading cause an error # Then it should be suggested to the user that they should provide JSON or YAML with pytest.raises(ValueError, match=YAML_LOADING_ERROR) as exc: schemathesis.from_uri(schema_url) if not without_content_type: # And list the actual response content type assert "The actual response has `text/html; charset=utf-8` Content-Type" in exc.value.args[ 0]
def test_add_link_behind_a_reference(schema_url): # See GH-824 schema = schemathesis.from_uri(schema_url) # When all methods for an API operation are behind a reference schema.raw_schema["components"]["methods"] = { "users": schema.raw_schema["paths"]["/users/"], "user-details": schema.raw_schema["paths"]["/users/{user_id}"], } schema.raw_schema["paths"]["/users/"] = { "$ref": "#/components/methods/users" } schema.raw_schema["paths"]["/users/{user_id}"] = { "$ref": "#/components/methods/user-details" } assert not hasattr(schema, "_operations") # And a link is added add_link(schema, schema["/users/{user_id}"]["GET"], parameters={"userId": "$response.body#/id"}) # Then the source API operation should have the new link operation = schema["/users/"]["POST"] links = operation.definition.resolved["responses"]["201"]["links"] assert len(links) == 3 assert links["GET /users/{user_id}"] == { "parameters": { "userId": "$response.body#/id" }, "operationId": "getUser" }
def test_call_and_validate(openapi3_schema_url): api_schema = schemathesis.from_uri(openapi3_schema_url) @given(case=api_schema["/success"]["GET"].as_strategy()) @settings(max_examples=1) def test(case): case.call_and_validate()
def test_get_operation_via_remote_reference(openapi_version, schema_url): schema = schemathesis.from_uri(schema_url) resolved = schema.get_operation_by_reference( f"{schema_url}#/paths/~1users~1{{user_id}}/patch") assert isinstance(resolved, APIOperation) assert resolved.path == "/users/{user_id}" assert resolved.method.upper() == "PATCH" # Via common parameters for all methods if openapi_version.is_openapi_2: assert resolved.query == ParameterSet([ OpenAPI20Parameter({ "in": "query", "name": "common", "required": True, "type": "integer" }) ]) if openapi_version.is_openapi_3: assert resolved.query == ParameterSet([ OpenAPI30Parameter({ "in": "query", "name": "common", "required": True, "schema": { "type": "integer" } }) ])
def test_serialize_interrupted(mocker, schema_url): mocker.patch( "schemathesis.runner.impl.solo.SingleThreadRunner._execute_impl", side_effect=KeyboardInterrupt) schema = schemathesis.from_uri(schema_url) events = from_schema(schema).execute() next(events) assert serialize_event(next(events)) == {"Interrupted": None}
def test_get_links(openapi3_base_url, schema_url, url, expected): schema = schemathesis.from_uri(schema_url) response = requests.post(f"{openapi3_base_url}{url}", json={"first_name": "TEST", "last_name": "TEST"}) tests = schema["/users/"]["POST"].get_stateful_tests(response, Stateful.links) assert len(tests) == len(expected) for test, value in zip(tests, expected): assert test.name == value.name assert test.parameters == value.parameters
def test_add_link_by_reference(schema_url): schema = schemathesis.from_uri(schema_url) links = add_link(schema, "#/paths/~1users~1{user_id}/get", parameters={"userId": "$response.body#/id"}) assert links["#/paths/~1users~1{user_id}/get"] == { "operationRef": "#/paths/~1users~1{user_id}/get", **EXPECTED_LINK_PARAMETERS, }
def test_get_links(openapi3_base_url, schema_url, url, expected): schema = schemathesis.from_uri(schema_url) response = requests.post(f"{openapi3_base_url}{url}", json={ "first_name": "TEST", "last_name": "TEST" }) assert schema["/users/"]["POST"].get_stateful_tests( response, Stateful.links) == expected
def test_add_link_no_operation_id(schema_url): schema = schemathesis.from_uri(schema_url) target = schema["/users/{user_id}"]["GET"] del target.definition.resolved["operationId"] links = add_link(schema, target, parameters={"userId": "$response.body#/id"}) assert links[f"{target.method.upper()} {target.path}"] == { "operationRef": "#/paths/~1users~1{user_id}/get", **EXPECTED_LINK_PARAMETERS, }
def test_add_link_nothing_is_provided(schema_url): schema = schemathesis.from_uri(schema_url) # When the user doesn't provide parameters or request_body with pytest.raises( ValueError, match="You need to provide `parameters` or `request_body`."): # Then there should be an error schema.add_link( source=schema["/users/"]["POST"], target="#/paths/~1users~1{user_id}/get", status_code="201", )
def test_serialize_event(schema_url): schema = schemathesis.from_uri(schema_url) events = from_schema(schema).execute() next(events) next(events) event = serialize_event(next(events)) assert "interactions" not in event["AfterExecution"]["result"] assert "logs" not in event["AfterExecution"]["result"] assert event["AfterExecution"]["result"]["checks"][0]["example"][ "query"] == { "id": ["0"] }
def test_port_override_with_ipv6(openapi3_schema_url, simple_openapi, mocker): resp = Response() resp.status_code = 200 resp._content = json.dumps(simple_openapi).encode("utf-8") mocker.patch("requests.get", return_value=resp) url = URL(openapi3_schema_url) parts = list(map(int, url.host.split("."))) ipv6_host = "2002:{:02x}{:02x}:{:02x}{:02x}::".format(*parts) ipv6 = url.with_host("[%s]" % ipv6_host) schema = schemathesis.from_uri(str(ipv6), validate_schema=False, port=8081) operation = next(schema.get_all_operations()).ok() assert operation.base_url == "http://[2002:7f00:1::]:8081/schema.yaml"
def test_read_only(schema_url): # When API operation has `readOnly` properties schema = schemathesis.from_uri(schema_url) @given(case=schema["/read_only"]["GET"].as_strategy()) @settings(max_examples=1, deadline=None) def test(case): # Then `writeOnly` should not affect the response schema response = case.call() assert "write" not in response.json() case.validate_response(response) test()
def test_add_link_default(schema_url): schema = schemathesis.from_uri(schema_url) # When we add a link to the target API operation # And it is an `APIOperation` instance # And it has the `operationId` key links = add_link(schema, schema["/users/{user_id}"]["GET"], parameters={"userId": "$response.body#/id"}) # Then it should be added without errors assert links[schema["/users/{user_id}"]["GET"].verbose_name] == { "operationId": "getUser", **EXPECTED_LINK_PARAMETERS, }
def test_misspelled_parameter(schema_url, parameter, message): schema = schemathesis.from_uri(schema_url) # When the user supplies a parameter definition, that points to location which has no parameters defined in the # schema add_link(schema, "#/paths/~1users~1{user_id}/get", parameters={f"header.{parameter}": "$response.body#/id"}) case = schema["/users/{user_id}"]["GET"].make_case() link = schema["/users/"]["POST"].links["201"][ "#/paths/~1users~1{user_id}/get"] with pytest.raises(ValueError, match=re.escape(message)): link.set_data(case, context=expressions.ExpressionContext(case=case, response=None))
def test_add_link_unknown_operation(schema_url, change, message): schema = schemathesis.from_uri(schema_url) # When the source API operation is modified and can't be found source = schema["/users/"]["POST"] change(schema, source) with pytest.raises( ValueError, match=re.escape( f"{message} Check if the requested API operation passes the filters in the schema." )): # Then there should be an error about it. schema.add_link(source=source, target="#/paths/~1users~1{user_id}/get", status_code="201", request_body="#/foo")
def test_optional_form_parameters(schema_url): # When form parameters are optional schema = schemathesis.from_uri(schema_url) strategy = schema["/multipart"]["POST"].as_strategy() @given(case=strategy) @settings(max_examples=3, deadline=None, suppress_health_check=[HealthCheck.too_slow, HealthCheck.filter_too_much]) def test(case): assume("maybe" in case.body) response = case.call() assert response.status_code == 200 # Then they still should be possible to generate assert response.json()["maybe"] == str(case.body["maybe"]) test()
def test_write_only(schema_url): # When API operation has `writeOnly` properties schema = schemathesis.from_uri(schema_url) @given(case=schema["/write_only"]["POST"].as_strategy()) @settings(max_examples=1) def test(case): # Then `writeOnly` should be used only in requests assert "write" in case.body assert "read" not in case.body # And `readOnly` should only occur in responses response = case.call() assert "write" not in response.json() case.validate_response(response) test()
def test_add_link_no_operations_cache(schema_url, status_code): schema = schemathesis.from_uri(schema_url) # When we add a link to the target API operation source = schema["/users/"]["POST"] target = schema["/users/{user_id}"]["GET"] # And the operations are not cached delattr(schema, "_operations") schema.add_link( source=source, target=target, status_code=status_code, parameters={"userId": "$response.body#/id"}, ) # Then it should be added without errors # And the cache cleanup should be no-op links = schema["/users/"]["POST"].definition.resolved["responses"]["201"][ "links"] assert links[f"{target.method.upper()} {target.path}"] == { "operationId": "getUser", **EXPECTED_LINK_PARAMETERS, }
def test_uri_loader_custom_kwargs(app, schema_url): # All custom kwargs are passed to `requests.get` schemathesis.from_uri(schema_url, verify=False, headers={"X-Test": "foo"}) request = app["schema_requests"][0] assert request.headers["X-Test"] == "foo" assert request.headers["User-Agent"] == USER_AGENT
import schemathesis from hypothesis import settings from schemathesis.checks import not_a_server_error schema = schemathesis.from_uri("https://petstore.swagger.io/v2/swagger.json") @schema.parametrize(method="GET", endpoint="/pet") @settings(max_examples=25) def test_get_booking(case): response = case.call() # assert response.status_code < 500 case.validate_response(response, checks=(not_a_server_error,))
API_PATH = os.getenv("API_URL") BASE_URL = os.getenv("BASE_URL") def handler(event, context): import pytest return pytest.main(['-o', 'cache_dir=/tmp/.testcache']) # will only be run if called from cli if __name__ == "__main__": test_event = { 'openapi_uri': 'tests/openapi_example.yaml', 'base_url': 'https://cloudstash.io' } test_context = {'env': {}} test_res = handler(test_event, test_context) print(test_res) schema = schemathesis.from_uri(API_PATH) @schema.parametrize() @settings(deadline=2000, print_blob=True, max_examples=10, verbosity=Verbosity.verbose) def test_api(case): response = case.call_and_validate() return response
def test_port_override(openapi3_schema_url): schema = schemathesis.from_uri(openapi3_schema_url, port=8081) operation = next(schema.get_all_operations()).ok() assert operation.base_url == "http://127.0.0.1:8081/schema.yaml"
def test_base_url(base_url, schema_url): schema = schemathesis.from_uri(schema_url) assert schema.base_url == base_url
def api_schema(request, openapi_version): if request.param == "aiohttp": schema_url = request.getfixturevalue("schema_url") return schemathesis.from_uri(schema_url) app = request.getfixturevalue("flask_app") return schemathesis.from_wsgi("/schema.yaml", app=app)
def test_base_url(openapi3_schema_url): schema = schemathesis.from_uri(openapi3_schema_url) assert schema.base_url is None
def test_uri_loader(app_schema, app, schema_url): # Each loader method should read the specified schema correctly assert schemathesis.from_uri(schema_url).raw_schema == app_schema
def test_base_url_override(openapi3_schema_url, url): schema = schemathesis.from_uri(openapi3_schema_url, base_url=url) operation = next(schema.get_all_operations()).ok() assert operation.base_url == "http://example.com"
def test_base_url_override(schema_url, url): schema = schemathesis.from_uri(schema_url, base_url=url) endpoint = next(schema.get_all_endpoints()) assert endpoint.base_url == "http://example.com"
def test_links_access(schema_url): schema = schemathesis.from_uri(schema_url) links = schema["/users/"]["POST"].links["201"] assert len(links) == 2 assert links["GetUserByUserId"].name == "GetUserByUserId"