-
-
Notifications
You must be signed in to change notification settings - Fork 146
/
conftest.py
214 lines (163 loc) · 5.53 KB
/
conftest.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
from textwrap import dedent
import pytest
from click.testing import CliRunner
import schemathesis.cli
from schemathesis.extra._aiohttp import run_server
from .apps import _aiohttp, _flask
from .utils import make_schema
pytest_plugins = ["pytester", "aiohttp.pytest_plugin", "pytest_mock"]
def pytest_configure(config):
config.addinivalue_line("markers", "endpoints(*names): add only specified endpoints to the test application.")
@pytest.fixture(scope="session")
def _app():
"""A global AioHTTP application with configurable endpoints."""
return _aiohttp.create_app(("success", "failure"))
@pytest.fixture
def endpoints(request):
marker = request.node.get_closest_marker("endpoints")
if marker:
endpoints = marker.args
else:
endpoints = ("success", "failure")
return endpoints
@pytest.fixture()
def app(_app, endpoints):
"""Set up the global app for a specific test.
NOTE. It might cause race conditions when `pytest-xdist` is used, but they have very low probability.
"""
_aiohttp.reset_app(_app, endpoints)
return _app
@pytest.fixture(scope="session")
def server(_app):
"""Run the app on an unused port."""
port = run_server(_app)
yield {"port": port}
@pytest.fixture()
def base_url(server, app):
"""Base URL for the running application."""
return f"http://127.0.0.1:{server['port']}"
@pytest.fixture()
def schema_url(base_url):
"""URL of the schema of the running application."""
return f"{base_url}/swagger.yaml"
@pytest.fixture(scope="session")
def cli():
"""CLI runner helper.
Provides in-process execution via `click.CliRunner` and sub-process execution via `pytest.pytester.Testdir`.
"""
cli_runner = CliRunner()
class Runner:
@staticmethod
def run(*args, **kwargs):
return cli_runner.invoke(schemathesis.cli.run, args, **kwargs)
@staticmethod
def main(*args, **kwargs):
return cli_runner.invoke(schemathesis.cli.schemathesis, args, **kwargs)
return Runner()
@pytest.fixture(scope="session")
def simple_schema():
return {
"swagger": "2.0",
"info": {"title": "Sample API", "description": "API description in Markdown.", "version": "1.0.0"},
"host": "api.example.com",
"basePath": "/v1",
"schemes": ["https"],
"paths": {
"/users": {
"get": {
"summary": "Returns a list of users.",
"description": "Optional extended description in Markdown.",
"produces": ["application/json"],
"responses": {"200": {"description": "OK"}},
}
}
},
}
@pytest.fixture(scope="session")
def swagger_20(simple_schema):
return schemathesis.from_dict(simple_schema)
@pytest.fixture(scope="session")
def openapi_30():
raw = make_schema("simple_openapi.yaml")
return schemathesis.from_dict(raw)
@pytest.fixture()
def app_schema():
return _aiohttp.make_schema(endpoints=("success", "failure"))
@pytest.fixture()
def testdir(testdir):
def maker(
content,
method=None,
endpoint=None,
tag=None,
pytest_plugins=("aiohttp.pytest_plugin",),
validate_schema=True,
schema=None,
**kwargs,
):
schema = schema or make_schema(**kwargs)
preparation = dedent(
"""
import pytest
import schemathesis
from test.utils import *
from hypothesis import given, settings, HealthCheck
raw_schema = {schema}
schema = schemathesis.from_dict(raw_schema, method={method}, endpoint={endpoint}, tag={tag}, validate_schema={validate_schema})
""".format(
schema=schema,
method=repr(method),
endpoint=repr(endpoint),
tag=repr(tag),
validate_schema=repr(validate_schema),
)
)
module = testdir.makepyfile(preparation, content)
testdir.makepyfile(
conftest=dedent(
f"""
pytest_plugins = {pytest_plugins}
def pytest_configure(config):
config.HYPOTHESIS_CASES = 0
def pytest_unconfigure(config):
print(f"Hypothesis calls: {{config.HYPOTHESIS_CASES}}")
"""
)
)
return module
testdir.make_test = maker
def make_importable_pyfile(*args, **kwargs):
module = testdir.makepyfile(*args, **kwargs)
make_importable(module)
return module
testdir.make_importable_pyfile = make_importable_pyfile
def run_and_assert(*args, **kwargs):
result = testdir.runpytest(*args)
result.assert_outcomes(**kwargs)
testdir.run_and_assert = run_and_assert
return testdir
@pytest.fixture()
def flask_app(endpoints):
return _flask.create_app(endpoints)
def make_importable(module):
"""Make the package importable by the inline CLI execution."""
pkgroot = module.dirpath()
module._ensuresyspath(True, pkgroot)
@pytest.fixture
def loadable_flask_app(testdir, endpoints):
module = testdir.make_importable_pyfile(
location=f"""
from test.apps._flask import create_app
app = create_app({endpoints})
"""
)
return f"{module.purebasename}:app"
@pytest.fixture
def loadable_aiohttp_app(testdir, endpoints):
module = testdir.make_importable_pyfile(
location=f"""
from test.apps._aiohttp import create_app
app = create_app({endpoints})
"""
)
return f"{module.purebasename}:app"