예제 #1
0
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)
예제 #2
0
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})
예제 #3
0
def case(endpoint):
    return Case(
        endpoint,
        path_parameters={"user_id": 5},
        query={"username": "******"},
        headers={"X-Token": "secret"},
        body={"a": 1},
    )
예제 #4
0
def case(operation):
    return Case(
        operation,
        path_parameters={"user_id": 5},
        query={"username": "******"},
        headers={"X-Token": "secret"},
        body={"a": 1},
    )
예제 #5
0
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)
예제 #6
0
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})]
예제 #7
0
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, ("", "."))
예제 #8
0
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})
예제 #9
0
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]
예제 #10
0
    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": {
예제 #11
0
              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(
        {
예제 #12
0
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")
예제 #13
0
    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"),
예제 #14
0
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 == {
예제 #15
0
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
예제 #16
0
                        ],
                        "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()
예제 #17
0
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
예제 #18
0
              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(
        {
예제 #19
0
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)
예제 #20
0
    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"),
예제 #21
0
def test_call(override, base_url):
    kwargs = {"method": "GET", "path": "/api/success"}
    if override:
        case = Case(**kwargs)
        response = case.call(base_url)