specmatic 0.8.2__py3-none-any.whl → 0.9.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of specmatic might be problematic. Click here for more details.
- specmatic/core/specmatic.py +81 -28
- specmatic/servers/asgi_app_server.py +3 -0
- specmatic/version.py +1 -1
- {specmatic-0.8.2.dist-info → specmatic-0.9.1.dist-info}/METADATA +14 -25
- {specmatic-0.8.2.dist-info → specmatic-0.9.1.dist-info}/RECORD +7 -7
- {specmatic-0.8.2.dist-info → specmatic-0.9.1.dist-info}/WHEEL +0 -0
- {specmatic-0.8.2.dist-info → specmatic-0.9.1.dist-info}/top_level.txt +0 -0
specmatic/core/specmatic.py
CHANGED
|
@@ -5,25 +5,38 @@ from specmatic.core.specmatic_test import SpecmaticTest
|
|
|
5
5
|
from specmatic.generators.pytest_generator import PyTestGenerator
|
|
6
6
|
from specmatic.generators.unittest_generator import UnitTestGenerator
|
|
7
7
|
from specmatic.servers.app_server import AppServer
|
|
8
|
+
from specmatic.servers.asgi_app_server import ASGIAppServer
|
|
9
|
+
from specmatic.servers.wsgi_app_server import WSGIAppServer
|
|
8
10
|
from specmatic.utils import get_junit_report_file_path
|
|
9
11
|
|
|
10
12
|
|
|
11
13
|
class Specmatic:
|
|
12
14
|
def __init__(self):
|
|
13
|
-
self.
|
|
15
|
+
self.app = None
|
|
16
|
+
self.app_module = ''
|
|
17
|
+
self.app_host = '127.0.0.1'
|
|
18
|
+
self.app_port = 0
|
|
19
|
+
self.reset_app_config_func = None
|
|
20
|
+
self.set_app_config_func = None
|
|
21
|
+
self.app_server = None
|
|
22
|
+
|
|
23
|
+
self.stub_host = None
|
|
24
|
+
self.stub_port = None
|
|
25
|
+
self.expectations = None
|
|
14
26
|
self.stub_args = None
|
|
27
|
+
self.stub = None
|
|
28
|
+
|
|
15
29
|
self.test_class = None
|
|
16
|
-
self.test_port = None
|
|
17
30
|
self.test_host = None
|
|
18
|
-
self.
|
|
19
|
-
self.
|
|
20
|
-
|
|
21
|
-
self.
|
|
31
|
+
self.test_port = None
|
|
32
|
+
self.test_args = None
|
|
33
|
+
|
|
34
|
+
self.project_root = ''
|
|
35
|
+
self.specmatic_json_file_path = ''
|
|
36
|
+
|
|
22
37
|
self.run_stub = False
|
|
23
38
|
self.run_app = False
|
|
24
39
|
self.run_tests = False
|
|
25
|
-
self.project_root = ''
|
|
26
|
-
self.specmatic_json_file_path = ''
|
|
27
40
|
|
|
28
41
|
def with_project_root(self, project_root):
|
|
29
42
|
self.project_root = project_root
|
|
@@ -33,7 +46,7 @@ class Specmatic:
|
|
|
33
46
|
self.specmatic_json_file_path = specmatic_json_file_path
|
|
34
47
|
return self
|
|
35
48
|
|
|
36
|
-
def
|
|
49
|
+
def with_stub(self, stub_host: str = '127.0.0.1', stub_port: int = 0, expectations=None, args=None):
|
|
37
50
|
self.stub_host = stub_host
|
|
38
51
|
self.stub_port = stub_port
|
|
39
52
|
self.run_stub = True
|
|
@@ -46,6 +59,26 @@ class Specmatic:
|
|
|
46
59
|
self.run_app = True
|
|
47
60
|
return self
|
|
48
61
|
|
|
62
|
+
def with_wsgi_app(self, app, host: str = '127.0.0.1', port: int = 0, set_app_config_func=None,
|
|
63
|
+
reset_app_config_func=None):
|
|
64
|
+
self.app = app
|
|
65
|
+
self.app_host = host
|
|
66
|
+
self.app_port = port
|
|
67
|
+
self.set_app_config_func = set_app_config_func
|
|
68
|
+
self.reset_app_config_func = reset_app_config_func
|
|
69
|
+
self.run_app = True
|
|
70
|
+
return self
|
|
71
|
+
|
|
72
|
+
def with_asgi_app(self, app_module: str, host: str = '127.0.0.1', port: int = 0, set_app_config_func=None,
|
|
73
|
+
reset_app_config_func=None):
|
|
74
|
+
self.app_module = app_module
|
|
75
|
+
self.app_host = host
|
|
76
|
+
self.app_port = port
|
|
77
|
+
self.set_app_config_func = set_app_config_func
|
|
78
|
+
self.reset_app_config_func = reset_app_config_func
|
|
79
|
+
self.run_app = True
|
|
80
|
+
return self
|
|
81
|
+
|
|
49
82
|
def test(self, test_class, test_host: str = '127.0.0.1', test_port: int = 0, args=None):
|
|
50
83
|
self.test_class = test_class
|
|
51
84
|
self.test_host = test_host
|
|
@@ -54,26 +87,46 @@ class Specmatic:
|
|
|
54
87
|
self.run_tests = True
|
|
55
88
|
return self
|
|
56
89
|
|
|
57
|
-
def
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
90
|
+
def __init_app_server(self):
|
|
91
|
+
if self.run_app:
|
|
92
|
+
if self.app is None and self.app_module == '':
|
|
93
|
+
raise Exception('Please specify either an app or an app_module.')
|
|
94
|
+
if self.app is not None and self.app_module != '':
|
|
95
|
+
raise Exception('Please specify only one of app or app_module, and not both.')
|
|
96
|
+
if self.app is not None:
|
|
97
|
+
self.app_server = WSGIAppServer(self.app, self.app_host, self.app_port, self.set_app_config_func,
|
|
98
|
+
self.reset_app_config_func)
|
|
99
|
+
else:
|
|
100
|
+
self.app_server = ASGIAppServer(self.app_module, self.app_host, self.app_port, self.set_app_config_func,
|
|
101
|
+
self.reset_app_config_func)
|
|
102
|
+
|
|
103
|
+
def __start_stub(self):
|
|
104
|
+
if self.run_stub:
|
|
105
|
+
self.stub = SpecmaticStub(self.stub_host, self.stub_port, self.project_root, self.specmatic_json_file_path,
|
|
106
|
+
self.stub_args)
|
|
107
|
+
self.stub.set_expectations(self.expectations)
|
|
108
|
+
self.app_server.set_app_config(self.stub.host, self.stub.port)
|
|
109
|
+
|
|
110
|
+
def __execute_tests(self):
|
|
111
|
+
if self.run_tests:
|
|
112
|
+
if self.app_server is not None:
|
|
65
113
|
self.app_server.start()
|
|
66
114
|
self.test_host = self.app_server.host
|
|
67
115
|
self.test_port = self.app_server.port
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
116
|
+
SpecmaticTest(self.test_host, self.test_port, self.project_root,
|
|
117
|
+
self.specmatic_json_file_path, self.test_args).run()
|
|
118
|
+
if issubclass(self.test_class, unittest.TestCase):
|
|
119
|
+
print("Injecting unittest methods")
|
|
120
|
+
UnitTestGenerator(self.test_class, get_junit_report_file_path()).generate()
|
|
121
|
+
else:
|
|
122
|
+
print("Injecting pytest methods")
|
|
123
|
+
PyTestGenerator(self.test_class, get_junit_report_file_path()).generate()
|
|
124
|
+
|
|
125
|
+
def run(self):
|
|
126
|
+
try:
|
|
127
|
+
self.__init_app_server()
|
|
128
|
+
self.__start_stub()
|
|
129
|
+
self.__execute_tests()
|
|
77
130
|
except Exception as e:
|
|
78
131
|
print(f"Error: {e}")
|
|
79
132
|
raise e
|
|
@@ -81,5 +134,5 @@ class Specmatic:
|
|
|
81
134
|
if self.app_server is not None:
|
|
82
135
|
self.app_server.stop()
|
|
83
136
|
self.app_server.reset_app_config()
|
|
84
|
-
if stub is not None:
|
|
85
|
-
stub.stop()
|
|
137
|
+
if self.stub is not None:
|
|
138
|
+
self.stub.stop()
|
|
@@ -43,6 +43,9 @@ class ASGIAppServer(AppServer):
|
|
|
43
43
|
def __read_process_output(self):
|
|
44
44
|
try:
|
|
45
45
|
for line in iter(self.__process.stdout.readline, ''):
|
|
46
|
+
if self.__process.poll() is not None:
|
|
47
|
+
line = line.decode()
|
|
48
|
+
raise Exception('App process terminated due to an error ' + line)
|
|
46
49
|
if line:
|
|
47
50
|
line = line.decode().rstrip()
|
|
48
51
|
print(line)
|
specmatic/version.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
__version__ = '0.
|
|
1
|
+
__version__ = '0.9.1'
|
|
2
2
|
__specmatic_version__ = '0.68.0'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: specmatic
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.9.1
|
|
4
4
|
Summary: A Python module for using the Specmatic Library.
|
|
5
5
|
Home-page: https://github.com/znsio/specmatic-python-extensions
|
|
6
6
|
Author: Specmatic Builders
|
|
@@ -45,28 +45,24 @@ The open api specification can be present either locally or in a [Central Contra
|
|
|
45
45
|
## WSGI Apps
|
|
46
46
|
|
|
47
47
|
#### To run contract tests with a stub for a wsgi app (like Flask):
|
|
48
|
-
|
|
49
|
-
``````app_server = WSGIAppServer(app, app_host, app_port)``````
|
|
50
|
-
- Note:
|
|
51
|
-
- The host and port are optional. If they are not specified, the app will be started on a random available port on 127.0.0.1.
|
|
52
|
-
- You would need a [specmatic.json](https://specmatic.in/documentation/specmatic_json.html) file to be present in the root directory of your project.
|
|
53
|
-
- To run tests using a stub for your dependencies:
|
|
48
|
+
|
|
54
49
|
``````
|
|
55
50
|
class TestContract:
|
|
56
51
|
pass
|
|
57
52
|
|
|
58
53
|
|
|
59
|
-
app_server = WSGIAppServer(app, app_host, app_port)
|
|
60
54
|
Specmatic() \
|
|
61
55
|
.with_project_root(PROJECT_ROOT) \
|
|
62
|
-
.
|
|
63
|
-
.app
|
|
56
|
+
.with_stub(stub_host, stub_port, [expectation_json_file]) \
|
|
57
|
+
.with_wsgi_app(app, app_host, app_port) \
|
|
64
58
|
.test(TestContract) \
|
|
65
59
|
.run()
|
|
66
60
|
``````
|
|
67
61
|
|
|
68
62
|
- In this, we are passing:
|
|
69
|
-
- an instance of
|
|
63
|
+
- an instance of your asgi app like flask
|
|
64
|
+
- app_host and app_port. If they are not specified, the app will be started on a random available port on 127.0.0.1.
|
|
65
|
+
- You would need a [specmatic.json](https://specmatic.in/documentation/specmatic_json.html) file to be present in the root directory of your project.
|
|
70
66
|
- an empty test class.
|
|
71
67
|
- stub_host, stub_port, optional list of json files to set expectations on the stub.
|
|
72
68
|
The stub_host, stub_port will be used to run the specmatic stub server.
|
|
@@ -83,11 +79,9 @@ Specmatic() \
|
|
|
83
79
|
class TestContract:
|
|
84
80
|
pass
|
|
85
81
|
|
|
86
|
-
|
|
87
|
-
app_server = WSGIAppServer(app, app_host, app_port)
|
|
88
82
|
Specmatic() \
|
|
89
83
|
.with_project_root(PROJECT_ROOT) \
|
|
90
|
-
.app
|
|
84
|
+
.with_wsgi_app(app, app_host, app_port) \
|
|
91
85
|
.test(TestContract) \
|
|
92
86
|
.run()
|
|
93
87
|
``````
|
|
@@ -95,20 +89,16 @@ Specmatic() \
|
|
|
95
89
|
## ASGI Apps
|
|
96
90
|
|
|
97
91
|
#### To run contract tests with a stub for an asgi app (like sanic):
|
|
98
|
-
-
|
|
99
|
-
``````app_server = ASGIAppServer('main:app', app_host, app_port)``````
|
|
100
|
-
If host and port are not specified, the app will be started on a random available port on 127.0.0.1.
|
|
101
|
-
- You can now use the ``````ASGIAppServer`````` object to run tests just like we do it for WSGI apps:
|
|
92
|
+
- If you are using an asgi app like sanic, fastapi, use the ``````with_asgi_app`````` function and pass it a string in the 'module:app' format.
|
|
102
93
|
``````
|
|
103
94
|
class TestContract:
|
|
104
95
|
pass
|
|
105
96
|
|
|
106
97
|
|
|
107
|
-
app_server = ASGIAppServer('main:app', app_host, app_port)
|
|
108
98
|
Specmatic() \
|
|
109
99
|
.with_project_root(PROJECT_ROOT) \
|
|
110
|
-
.
|
|
111
|
-
.app
|
|
100
|
+
.with_stub(stub_host, stub_port, [expectation_json_file]) \
|
|
101
|
+
.with_asgi_app('main:app', app_host, app_port) \
|
|
112
102
|
.test(TestContract) \
|
|
113
103
|
.run()
|
|
114
104
|
``````
|
|
@@ -120,18 +110,17 @@ class TestContract:
|
|
|
120
110
|
pass
|
|
121
111
|
|
|
122
112
|
|
|
123
|
-
app_server = WSGIAppServer(app, app_host, app_port)
|
|
124
113
|
Specmatic() \
|
|
125
114
|
.with_project_root(PROJECT_ROOT) \
|
|
126
|
-
.
|
|
127
|
-
.app
|
|
115
|
+
.with_stub(stub_host, stub_port, [expectation_json_file], ['--strict']) \
|
|
116
|
+
.with_wsgi_app(app, port=app_port) \
|
|
128
117
|
.test(TestContract, args=['--testBaseURL=http://localhost:5000']) \
|
|
129
118
|
.run()
|
|
130
119
|
``````
|
|
131
120
|
|
|
132
121
|
## Common Issues
|
|
133
122
|
- **'Error loading ASGI app'**
|
|
134
|
-
This error occurs
|
|
123
|
+
This error occurs when an incorrect app module string is passed to the ``````with_asgi_app`````` function.
|
|
135
124
|
|
|
136
125
|
#### Solutions:
|
|
137
126
|
- Try to identify the correct module in which your app variable is instantiated/imported.
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
specmatic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
2
|
specmatic/utils.py,sha256=6JDPqpO51ykl0MWCOa32jkUOXZ-0RZ6N5Ng9_7r7XaU,519
|
|
3
|
-
specmatic/version.py,sha256=
|
|
3
|
+
specmatic/version.py,sha256=MpN_PFJMmvrp-2TOtwaw16FhamYEEkOXXdUWtIOP4YM,55
|
|
4
4
|
specmatic/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
5
|
specmatic/core/decorators.py,sha256=_TWZMbUyH4WFyYHzW0oBcuef-c6ktukJ9Av3iYrDkTY,2879
|
|
6
6
|
specmatic/core/specmatic.jar,sha256=LIHTAPFuGtfZ6zvcrwfVJ7luLAuSvMvDoalInN3pqUQ,87155557
|
|
7
|
-
specmatic/core/specmatic.py,sha256=
|
|
7
|
+
specmatic/core/specmatic.py,sha256=avagtEtRnfxUFqwHR3q-vIB0YdypJTsWEmQVA6DPXQQ,5361
|
|
8
8
|
specmatic/core/specmatic_base.py,sha256=sueXRmjXXLV8YC_3rsxGng2bPt2qWIsTWEO2A9MXMP0,1497
|
|
9
9
|
specmatic/core/specmatic_stub.py,sha256=_I6jc8oI7me6Q64gtPchRRqA-c8GGO5YTCIpw1nrwEo,4563
|
|
10
10
|
specmatic/core/specmatic_test.py,sha256=rZXCeTlH-3wkShJECL7VDN2hlkJgmuiKQYzVRwnLNok,994
|
|
@@ -14,10 +14,10 @@ specmatic/generators/test_generator_base.py,sha256=bCdJD9MOUX6FINPF2r06y9NQ5k10q
|
|
|
14
14
|
specmatic/generators/unittest_generator.py,sha256=Vkm8BP-_rZ-tFbLwUTNc90OgQCMJ4OHd8w5mShhcFyU,713
|
|
15
15
|
specmatic/servers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
16
|
specmatic/servers/app_server.py,sha256=kOZviJA7-F4kmMTLGiBln2oO5uYX28wKJM2xQJTOVQY,456
|
|
17
|
-
specmatic/servers/asgi_app_server.py,sha256=
|
|
17
|
+
specmatic/servers/asgi_app_server.py,sha256=yn3tpWoF-nP8labOJdn49UB85vKiqIELVXk-gAugcUc,2924
|
|
18
18
|
specmatic/servers/wsgi_app_server.py,sha256=3aU-o6Hh8FrnZlbjCLLpGY92HvJoU_rcqsZIb9TKVr8,1342
|
|
19
19
|
specmatic/servers/wsgi_server_thread.py,sha256=XUEYW7-FP1a-5EkQVGc3FI_jkDQBocArxHLiCn3JJvc,691
|
|
20
|
-
specmatic-0.
|
|
21
|
-
specmatic-0.
|
|
22
|
-
specmatic-0.
|
|
23
|
-
specmatic-0.
|
|
20
|
+
specmatic-0.9.1.dist-info/METADATA,sha256=OwazAuFZ4kT_CqWPPI914IixxOgtBreA9Ivspedn4d0,5717
|
|
21
|
+
specmatic-0.9.1.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
|
|
22
|
+
specmatic-0.9.1.dist-info/top_level.txt,sha256=E7kQ78YacKBoKKeKWR_N83exlG8r5J0wlzlGqFmvIfo,10
|
|
23
|
+
specmatic-0.9.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|