def test_wrong_schema_type(check): schema = BaseSchema({}) # These checks should not be valid for some generic schema case = Case( operation=APIOperation("", "", None, verbose_name="", schema=schema)) with pytest.raises(TypeError): check(requests.Response(), case)
def test_get_examples(name, swagger_20): if name == "body": # In Open API 2.0, the `body` parameter has a name, which is ignored # But we'd like to use this object as a payload; therefore, we put one extra level of nesting example = expected = {"name": "John"} media_type = "application/json" cls = PayloadAlternatives else: example = "John" expected = {"name": example} media_type = None # there is no payload cls = ParameterSet endpoint = make_endpoint( swagger_20, **{ name: cls( [ OpenAPI20Parameter( { "in": name, "name": "name", "required": True, "type": "string", "x-example": example, } ) ] ) }, ) strategies = endpoint.get_strategies_from_examples() assert len(strategies) == 1 assert strategies[0].example() == Case(endpoint, media_type=media_type, **{name: expected})
def case(endpoint): return Case( endpoint, path_parameters={"user_id": 5}, query={"username": "******"}, headers={"X-Token": "secret"}, body={"a": 1}, )
def case(operation): return Case( operation, path_parameters={"user_id": 5}, query={"username": "******"}, headers={"X-Token": "secret"}, body={"a": 1}, )
def test_as_requests_kwargs(override, server, base_url, converter): base_url = converter(base_url) kwargs = { "method": "GET", "path": "/api/success", "cookies": { "TOKEN": "secret" } } if override: case = Case(**kwargs) data = case.as_requests_kwargs(base_url)
def test_get_examples(name, swagger_20): example = {"name": "John"} endpoint = make_endpoint( swagger_20, **{ name: { "required": ["name"], "type": "object", "additionalProperties": False, "properties": {"name": {"type": "string"}}, "example": example, } }, ) assert list(get_examples(endpoint)) == [Case(endpoint, **{name: example})]
def test_keyboard_interrupt(cli, cli_args, base_url, mocker, flask_app, swagger_20, workers): # When a Schemathesis run in interrupted by keyboard or via SIGINT endpoint = Endpoint("/success", "GET", {}, swagger_20, base_url=base_url) if len(cli_args) == 2: endpoint.app = flask_app original = Case(endpoint).call_wsgi else: original = Case(endpoint).call counter = 0 def mocked(*args, **kwargs): nonlocal counter counter += 1 if counter > 1: # For threaded case it emulates SIGINT for the worker thread raise KeyboardInterrupt return original(*args, **kwargs) if len(cli_args) == 2: mocker.patch("schemathesis.Case.call_wsgi", wraps=mocked) else: mocker.patch("schemathesis.Case.call", wraps=mocked) result = cli.run(*cli_args, f"--workers={workers}") assert result.exit_code == ExitCode.OK # Then execution stops and a message about interruption is displayed lines = result.stdout.strip().split("\n") # And summary is still displayed in the end of the output if workers == 1: assert lines[10].startswith("GET /api/failure .") assert lines[10].endswith("[ 50%]") assert lines[11] == "GET /api/success " assert "!! KeyboardInterrupt !!" in lines[12] assert "== SUMMARY ==" in lines[14] else: assert_threaded_executor_interruption(lines, ("", "."))
def test_get_examples(name, swagger_20): example = {"name": "John"} endpoint = make_endpoint( swagger_20, **{ name: { "required": ["name"], "type": "object", "additionalProperties": False, "properties": {"name": {"type": "string"}}, "example": example, } }, ) strategies = endpoint.get_strategies_from_examples() assert len(strategies) == 1 assert strategies[0].example() == Case(endpoint, **{name: example})
def test_keyboard_interrupt(testdir, cli, schema_url, base_url, mocker): # When a Schemathesis run in interrupted by keyboard or via SIGINT original = Case("/success", "GET", base_url=base_url).call counter = 0 def mocked(*args, **kwargs): nonlocal counter counter += 1 if counter > 1: raise KeyboardInterrupt return original(*args, **kwargs) mocker.patch("schemathesis.Case.call", wraps=mocked) result = cli.run(schema_url) assert result.exit_code == ExitCode.OK # Then execution stops and a message about interruption is displayed lines = result.stdout.strip().split("\n") assert lines[9].startswith("GET /api/failure .") assert lines[9].endswith("[ 50%]") assert lines[10] == "GET /api/success " assert "!! KeyboardInterrupt !!" in lines[11] # And summary is still displayed in the end of the output assert "== SUMMARY ==" in lines[13]
strategy = schema["/cookies"]["GET"].as_strategy() @given(case=strategy) @settings(max_examples=3, suppress_health_check=[HealthCheck.filter_too_much], deadline=None) def test(case): response = case.call_asgi() assert response.status_code == 200 assert response.json() == {"token": "test"} test() def test_not_app_with_asgi(schema): case = Case(schema["/users"]["GET"]) case.operation.app = None with pytest.raises( RuntimeError, match="ASGI application instance is required. " "Please, set `app` argument in the schema constructor or pass it to `call_asgi`", ): case.call_asgi() def test_base_url(): # See GH-1366 # When base URL has non-empty base path raw_schema = { "openapi": "3.0.3", "info": {
deadline=None) def test(case): response = case.call_wsgi() assert response.status_code == 200 # converted to string in the app assert response.json == { key: str(value) for key, value in case.body.items() } test() def test_not_wsgi(schema): # When a schema is created without a WSGI app (e.g. from a URL) case = Case(schema.endpoints["/success"]["GET"]) case.endpoint.app = None # Then an error should be raised if the user tries to use `call_wsgi` with pytest.raises( RuntimeError, match="WSGI application instance is required. " "Please, set `app` argument in the schema constructor or pass it to `call_wsgi`", ): case.call_wsgi() @pytest.mark.hypothesis_nested def test_binary_body(mocker, flask_app): # When an endpoint accepts a binary input schema = schemathesis.from_dict( {
from test.apps._fastapi.app import app import pytest import schemathesis from schemathesis import Case from schemathesis.constants import USER_AGENT schema = schemathesis.from_dict(app.openapi()) @pytest.mark.parametrize("headers", (None, {"X-Key": "42"})) @schema.parametrize() def test_as_curl_command(case: Case, headers): command = case.as_curl_command(headers) expected_headers = "" if not headers else " ".join( f" -H '{name}: {value}'" for name, value in headers.items()) assert command == f"curl -X GET -H 'User-Agent: {USER_AGENT}'{expected_headers} http://localhost/users" def test_non_utf_8_body(): case = Case(operation=schema["/users"]["GET"], body=b"42\xff", media_type="application/octet-stream") command = case.as_curl_command() assert ( command == "curl -X GET -H 'Content-Length: 3' -H 'Content-Type: application/octet-stream' " f"-H 'User-Agent: {USER_AGENT}' -d '42�' http://localhost/users")
with pytest.raises(RuntimeExpressionError): expressions.evaluate(expr, context) @given(expr=(st.text() | (st.lists(st.sampled_from([".", "}", "{", "$"]) | st.text()).map( "".join)))) def test_random_expression(expr): try: expressions.evaluate(expr, context) except RuntimeExpressionError: pass def test_non_json_serializable_body(endpoint, response): case = Case(endpoint, body={"a": b"content"}) context = expressions.ExpressionContext(response=response, case=case) with pytest.raises(RuntimeExpressionError, match="^The request body is not JSON-serializable$"): expressions.evaluate("$request.body", context=context) @pytest.mark.parametrize( "expr, expected", ( ("$url", [Token.variable("$url")]), ("foo", [Token.string("foo")]), ("foo1", [Token.string("foo1")]), ("{}", [Token.lbracket(), Token.rbracket()]), ("{foo}", [Token.lbracket(), Token.string("foo"),
import pytest import requests from schemathesis import Case def test_path(): case = Case(method="GET", path="/users/{name}", path_parameters={"name": "test"}) assert case.formatted_path == "/users/test" @pytest.mark.parametrize("override", (False, True)) @pytest.mark.parametrize("converter", (lambda x: x, lambda x: x + "/")) def test_as_requests_kwargs(override, server, base_url, converter): base_url = converter(base_url) kwargs = { "method": "GET", "path": "/api/success", "cookies": { "TOKEN": "secret" } } if override: case = Case(**kwargs) data = case.as_requests_kwargs(base_url) else: case = Case(base_url=base_url, **kwargs) data = case.as_requests_kwargs() assert data == {
def test_warning(swagger_20): example = {"name": "John"} endpoint = make_endpoint(swagger_20, query={"example": example}) with pytest.warns(None) as record: assert list(get_examples(endpoint)) == [Case(endpoint, query=example)] assert not record
], "responses": {"200": {"description": "OK"}}, } } }, }, app=fastapi_app, ) strategy = schema.endpoints["/cookies"]["GET"].as_strategy() @given(case=strategy) @settings(max_examples=3, suppress_health_check=[HealthCheck.filter_too_much], deadline=None) def test(case): response = case.call_asgi() assert response.status_code == 200 assert response.json() == {"token": "test"} test() def test_not_app_with_asgi(schema): case = Case(schema.endpoints["/users"]["GET"]) case.endpoint.app = None with pytest.raises( RuntimeError, match="ASGI application instance is required. " "Please, set `app` argument in the schema constructor or pass it to `call_asgi`", ): case.call_asgi()
import requests from schemathesis import Case def test_path(): case = Case(method="GET", path="/users/{name}", path_parameters={"name": "test"}) assert case.formatted_path == "/users/test" def test_as_requests_kwargs(server, base_url): case = Case(method="GET", path="/api/success") data = case.as_requests_kwargs(base_url) assert data == { "headers": {}, "json": {}, "method": "GET", "params": {}, "url": f"http://127.0.0.1:{server['port']}/api/success", } response = requests.request(**data) assert response.status_code == 200 assert response.json() == {"success": True} def test_call(base_url): case = Case(method="GET", path="/api/success") response = case.call(base_url) assert response.status_code == 200
deadline=None) def test(case): response = case.call_wsgi() assert response.status_code == 200 # converted to string in the app assert response.json == { key: str(value) for key, value in case.body.items() } test() def test_not_wsgi(schema): # When a schema is created without a WSGI app (e.g. from a URL) case = Case(schema["/success"]["GET"]) case.operation.app = None # Then an error should be raised if the user tries to use `call_wsgi` with pytest.raises( RuntimeError, match="WSGI application instance is required. " "Please, set `app` argument in the schema constructor or pass it to `call_wsgi`", ): case.call_wsgi() @pytest.mark.hypothesis_nested def test_binary_body(mocker, flask_app): # When an API operation accepts a binary input schema = schemathesis.from_dict( {
def test_wrong_schema_type(check): schema = BaseSchema({}) # These checks should not be valid for some generic schema case = Case(endpoint=Endpoint("", "", None, schema=schema)) with pytest.raises(TypeError): check(requests.Response(), case)
with pytest.raises(RuntimeExpressionError): expressions.evaluate(expr, context) @given(expr=(st.text() | (st.lists(st.sampled_from([".", "}", "{", "$"]) | st.text()).map( "".join)))) def test_random_expression(expr): try: expressions.evaluate(expr, context) except RuntimeExpressionError: pass def test_non_json_serializable_body(operation, response): case = Case(operation, body={"a": b"content"}) context = expressions.ExpressionContext(response=response, case=case) with pytest.raises(RuntimeExpressionError, match="^The request body is not JSON-serializable$"): expressions.evaluate("$request.body", context=context) @pytest.mark.parametrize( "expr, expected", ( ("$url", [Token.variable("$url")]), ("foo", [Token.string("foo")]), ("foo1", [Token.string("foo1")]), ("{}", [Token.lbracket(), Token.rbracket()]), ("{foo}", [Token.lbracket(), Token.string("foo"),
def test_call(override, base_url): kwargs = {"method": "GET", "path": "/api/success"} if override: case = Case(**kwargs) response = case.call(base_url)