httpdbg 0.29.2__tar.gz → 0.30.0__tar.gz
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.
- {httpdbg-0.29.2 → httpdbg-0.30.0}/PKG-INFO +2 -1
- {httpdbg-0.29.2 → httpdbg-0.30.0}/README.md +1 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/__init__.py +1 -1
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/hooks/all.py +4 -2
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/hooks/external.py +1 -0
- httpdbg-0.30.0/httpdbg/hooks/unittest.py +263 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/mode_script.py +11 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg.egg-info/PKG-INFO +2 -1
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg.egg-info/SOURCES.txt +3 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/tests/test_api.py +2 -2
- httpdbg-0.30.0/tests/test_hook_pytest.py +38 -0
- httpdbg-0.30.0/tests/test_hook_unittest.py +132 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/tests/test_initiator.py +6 -6
- {httpdbg-0.29.2 → httpdbg-0.30.0}/tests/test_mode_module_pytest.py +0 -25
- {httpdbg-0.29.2 → httpdbg-0.30.0}/LICENSE +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/__main__.py +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/args.py +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/env.py +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/exception.py +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/hooks/__init__.py +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/hooks/aiohttp.py +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/hooks/generic.py +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/hooks/httpx.py +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/hooks/pytest.py +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/hooks/requests.py +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/hooks/socket.py +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/hooks/urllib3.py +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/hooks/utils.py +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/initiator.py +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/log.py +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/mode_console.py +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/mode_module.py +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/preview.py +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/records.py +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/server.py +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/utils.py +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/webapp/__init__.py +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/webapp/api.py +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/webapp/app.py +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/webapp/static/api.js +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/webapp/static/column.css +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/webapp/static/configuration.js +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/webapp/static/detail.css +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/webapp/static/favicon.ico +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/webapp/static/filter.js +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/webapp/static/icons/chevron-direction-top-outline-icon.svg +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/webapp/static/icons/download-install-line-icon.svg +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/webapp/static/icons/engine-gears-icon.svg +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/webapp/static/icons/files-papers-outline-icon.svg +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/webapp/static/icons/filter-outline-icon.svg +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/webapp/static/icons/information-mark-circle-outline-icon.svg +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/webapp/static/icons/math-multiplication-icon.svg +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/webapp/static/icons/push-pin-green-icon.svg +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/webapp/static/icons/question-mark-round-line-icon.svg +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/webapp/static/icons/recycle-bin-line-icon.svg +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/webapp/static/icons/wait-sandclock-icon.svg +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/webapp/static/index.htm +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/webapp/static/main.js +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/webapp/static/mustache.min.js +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/webapp/static/render.js +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/webapp/static/style.css +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/webapp/static/table.css +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg.egg-info/dependency_links.txt +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg.egg-info/entry_points.txt +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg.egg-info/requires.txt +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg.egg-info/top_level.txt +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/pyproject.toml +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/setup.cfg +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/tests/test_cli.py +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/tests/test_context_manager.py +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/tests/test_hook_aiohttp.py +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/tests/test_hook_httpx.py +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/tests/test_hook_requests.py +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/tests/test_hook_urllib3.py +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/tests/test_mode_console.py +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/tests/test_mode_script.py +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/tests/test_preview.py +0 -0
- {httpdbg-0.29.2 → httpdbg-0.30.0}/tests/test_server.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: httpdbg
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.30.0
|
|
4
4
|
Summary: A very simple tool to debug HTTP(S) client requests
|
|
5
5
|
Author-email: cle-b <cle@tictac.pm>
|
|
6
6
|
License: Apache-2.0
|
|
@@ -116,6 +116,7 @@ You can use any package as an initiator, this is not limited to HTTP requests.
|
|
|
116
116
|
| httpx | supported |
|
|
117
117
|
| aiohttp | supported |
|
|
118
118
|
| pytest | supported |
|
|
119
|
+
| unittest | supported |
|
|
119
120
|
| _your_package_ | yes, with the arg _-i your_package_ |
|
|
120
121
|
|
|
121
122
|
## configuration
|
|
@@ -88,6 +88,7 @@ You can use any package as an initiator, this is not limited to HTTP requests.
|
|
|
88
88
|
| httpx | supported |
|
|
89
89
|
| aiohttp | supported |
|
|
90
90
|
| pytest | supported |
|
|
91
|
+
| unittest | supported |
|
|
91
92
|
| _your_package_ | yes, with the arg _-i your_package_ |
|
|
92
93
|
|
|
93
94
|
## configuration
|
|
@@ -11,6 +11,7 @@ from httpdbg.hooks.httpx import hook_httpx
|
|
|
11
11
|
from httpdbg.hooks.pytest import hook_pytest
|
|
12
12
|
from httpdbg.hooks.requests import hook_requests
|
|
13
13
|
from httpdbg.hooks.socket import hook_socket
|
|
14
|
+
from httpdbg.hooks.unittest import hook_unittest
|
|
14
15
|
from httpdbg.hooks.urllib3 import hook_urllib3
|
|
15
16
|
from httpdbg.records import HTTPRecords
|
|
16
17
|
|
|
@@ -29,5 +30,6 @@ def httprecord(
|
|
|
29
30
|
with hook_urllib3(records):
|
|
30
31
|
with hook_aiohttp(records):
|
|
31
32
|
with hook_pytest(records):
|
|
32
|
-
with
|
|
33
|
-
|
|
33
|
+
with hook_unittest(records):
|
|
34
|
+
with hook_generic(records, initiators):
|
|
35
|
+
yield records
|
|
@@ -15,6 +15,7 @@ from httpdbg.records import HTTPRecords
|
|
|
15
15
|
@contextmanager
|
|
16
16
|
def watcher_external(records: HTTPRecords) -> Generator[HTTPRecords, None, None]:
|
|
17
17
|
try:
|
|
18
|
+
watcher = None
|
|
18
19
|
if HTTPDBG_SUBPROCESS_DIR not in os.environ:
|
|
19
20
|
with tempfile.TemporaryDirectory(
|
|
20
21
|
prefix="httpdbg"
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
from collections.abc import Callable
|
|
3
|
+
from contextlib import contextmanager
|
|
4
|
+
import inspect
|
|
5
|
+
import os
|
|
6
|
+
import typing
|
|
7
|
+
from typing import Generator
|
|
8
|
+
|
|
9
|
+
from httpdbg.initiator import httpdbg_group
|
|
10
|
+
from httpdbg.initiator import httpdbg_tag
|
|
11
|
+
from httpdbg.hooks.utils import decorate
|
|
12
|
+
from httpdbg.hooks.utils import getcallargs
|
|
13
|
+
from httpdbg.hooks.utils import undecorate
|
|
14
|
+
from httpdbg.records import HTTPRecords
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def set_hook_for_unittest_run(records: HTTPRecords, method: Callable):
|
|
18
|
+
|
|
19
|
+
def hook(*args, **kwargs):
|
|
20
|
+
callargs = getcallargs(method, *args, **kwargs)
|
|
21
|
+
|
|
22
|
+
if "self" in callargs:
|
|
23
|
+
test_case = callargs["self"]
|
|
24
|
+
|
|
25
|
+
label = "unknown test"
|
|
26
|
+
full_label = "unknown test"
|
|
27
|
+
|
|
28
|
+
method_name = getattr(test_case, "_testMethodName")
|
|
29
|
+
if method_name:
|
|
30
|
+
test_class_name = test_case.__class__.__name__
|
|
31
|
+
label = f"{test_class_name}::{method_name}"
|
|
32
|
+
full_label = label
|
|
33
|
+
test_module = inspect.getmodule(test_case.__class__)
|
|
34
|
+
test_module_path = getattr(test_module, "__file__")
|
|
35
|
+
if test_module_path:
|
|
36
|
+
test_module_path = os.path.relpath(test_module_path)
|
|
37
|
+
full_label = f"{test_module_path}::{full_label}"
|
|
38
|
+
|
|
39
|
+
with httpdbg_group(records, label, full_label):
|
|
40
|
+
ret = method(*args, **kwargs)
|
|
41
|
+
else:
|
|
42
|
+
ret = method(*args, **kwargs)
|
|
43
|
+
return ret
|
|
44
|
+
|
|
45
|
+
return hook
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def set_hook_for_unittest_fixture(_: HTTPRecords, method: Callable):
|
|
49
|
+
|
|
50
|
+
def hook(*args, **kwargs):
|
|
51
|
+
|
|
52
|
+
if getattr(method, "__name__") == "_callSetUp":
|
|
53
|
+
with httpdbg_tag("setUp"):
|
|
54
|
+
return method(*args, **kwargs)
|
|
55
|
+
elif getattr(method, "__name__") == "_callTearDown":
|
|
56
|
+
with httpdbg_tag("tearDown"):
|
|
57
|
+
return method(*args, **kwargs)
|
|
58
|
+
else:
|
|
59
|
+
return method(*args, **kwargs)
|
|
60
|
+
|
|
61
|
+
return hook
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def set_hook_for_unittest_class_setup(records: HTTPRecords, method: Callable):
|
|
65
|
+
|
|
66
|
+
def hook(*args, **kwargs):
|
|
67
|
+
callargs = getcallargs(method, *args, **kwargs)
|
|
68
|
+
|
|
69
|
+
if "test" in callargs:
|
|
70
|
+
test_case = callargs["test"]
|
|
71
|
+
|
|
72
|
+
test_class_name = test_case.__class__.__name__
|
|
73
|
+
label = f"{test_class_name}::setUpClass"
|
|
74
|
+
full_label = label
|
|
75
|
+
|
|
76
|
+
test_module = inspect.getmodule(test_case.__class__)
|
|
77
|
+
test_module_path = getattr(test_module, "__file__")
|
|
78
|
+
if test_module_path:
|
|
79
|
+
test_module_path = os.path.relpath(test_module_path)
|
|
80
|
+
full_label = f"{test_module_path}::{full_label}"
|
|
81
|
+
|
|
82
|
+
with httpdbg_group(records, label, full_label):
|
|
83
|
+
return method(*args, **kwargs)
|
|
84
|
+
else:
|
|
85
|
+
return method(*args, **kwargs)
|
|
86
|
+
|
|
87
|
+
return hook
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def set_hook_for_unittest_class_teardown(records: HTTPRecords, method: Callable):
|
|
91
|
+
|
|
92
|
+
def hook(*args, **kwargs):
|
|
93
|
+
callargs = getcallargs(method, *args, **kwargs)
|
|
94
|
+
|
|
95
|
+
test_result = None
|
|
96
|
+
if "result" in callargs:
|
|
97
|
+
result = callargs["result"]
|
|
98
|
+
|
|
99
|
+
if result.testsRun > 0:
|
|
100
|
+
test_result = result
|
|
101
|
+
|
|
102
|
+
if test_result:
|
|
103
|
+
|
|
104
|
+
label = "tearDownClass (unknown class)"
|
|
105
|
+
full_label = label
|
|
106
|
+
|
|
107
|
+
test_class = getattr(test_result, "_previousTestClass")
|
|
108
|
+
if test_class:
|
|
109
|
+
test_class_name = test_class.__name__
|
|
110
|
+
label = f"{test_class_name}::tearDownClass"
|
|
111
|
+
full_label = label
|
|
112
|
+
|
|
113
|
+
test_module = inspect.getmodule(test_class)
|
|
114
|
+
test_module_path = getattr(test_module, "__file__")
|
|
115
|
+
if test_module_path:
|
|
116
|
+
test_module_path = os.path.relpath(test_module_path)
|
|
117
|
+
full_label = f"{test_module_path}::{full_label}"
|
|
118
|
+
|
|
119
|
+
with httpdbg_group(records, label, full_label):
|
|
120
|
+
return method(*args, **kwargs)
|
|
121
|
+
else:
|
|
122
|
+
return method(*args, **kwargs)
|
|
123
|
+
|
|
124
|
+
return hook
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def set_hook_for_unittest_module_setup(records: HTTPRecords, method: Callable):
|
|
128
|
+
|
|
129
|
+
def hook(*args, **kwargs):
|
|
130
|
+
callargs = getcallargs(method, *args, **kwargs)
|
|
131
|
+
|
|
132
|
+
if "test" in callargs:
|
|
133
|
+
test_suite = callargs["test"]
|
|
134
|
+
|
|
135
|
+
test_module = inspect.getmodule(test_suite)
|
|
136
|
+
|
|
137
|
+
label = f"setUpModule ({test_module.__name__})" # may be __main__
|
|
138
|
+
full_label = label
|
|
139
|
+
|
|
140
|
+
test_module_path = getattr(test_module, "__file__")
|
|
141
|
+
if test_module_path:
|
|
142
|
+
# if we execute the tests using the script mode, the module name is __main__
|
|
143
|
+
# this is why we retrieve the module name from the path
|
|
144
|
+
module_name = os.path.splitext(os.path.basename(test_module_path))[0]
|
|
145
|
+
label = f"setUpModule ({module_name})"
|
|
146
|
+
|
|
147
|
+
test_module_path = os.path.relpath(test_module_path)
|
|
148
|
+
full_label = f"{test_module_path}::setUpModule"
|
|
149
|
+
|
|
150
|
+
with httpdbg_group(records, label, full_label):
|
|
151
|
+
return method(*args, **kwargs)
|
|
152
|
+
else:
|
|
153
|
+
return method(*args, **kwargs)
|
|
154
|
+
|
|
155
|
+
return hook
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def set_hook_for_unittest_module_teardown(records: HTTPRecords, method: Callable):
|
|
159
|
+
|
|
160
|
+
def hook(*args, **kwargs):
|
|
161
|
+
callargs = getcallargs(method, *args, **kwargs)
|
|
162
|
+
|
|
163
|
+
test_result = None
|
|
164
|
+
if "result" in callargs:
|
|
165
|
+
result = callargs["result"]
|
|
166
|
+
|
|
167
|
+
if result.testsRun > 0:
|
|
168
|
+
test_result = result
|
|
169
|
+
|
|
170
|
+
if test_result:
|
|
171
|
+
|
|
172
|
+
label = "tearDownModule (unknown module)"
|
|
173
|
+
full_label = label
|
|
174
|
+
|
|
175
|
+
test_class = getattr(test_result, "_previousTestClass")
|
|
176
|
+
if test_class:
|
|
177
|
+
|
|
178
|
+
test_module = inspect.getmodule(test_class)
|
|
179
|
+
|
|
180
|
+
label = f"tearDownModule ({test_module.__name__})" # may be __main__
|
|
181
|
+
|
|
182
|
+
test_module_path = getattr(test_module, "__file__")
|
|
183
|
+
if test_module_path:
|
|
184
|
+
# if we execute the tests using the script mode, the module name is __main__
|
|
185
|
+
# this is why we retrieve the module name from the path
|
|
186
|
+
module_name = os.path.splitext(os.path.basename(test_module_path))[
|
|
187
|
+
0
|
|
188
|
+
]
|
|
189
|
+
label = f"tearDownModule ({module_name})"
|
|
190
|
+
|
|
191
|
+
test_module_path = os.path.relpath(test_module_path)
|
|
192
|
+
full_label = f"{test_module_path}::tearDownModule"
|
|
193
|
+
|
|
194
|
+
with httpdbg_group(records, label, full_label):
|
|
195
|
+
return method(*args, **kwargs)
|
|
196
|
+
else:
|
|
197
|
+
return method(*args, **kwargs)
|
|
198
|
+
|
|
199
|
+
return hook
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
@typing.no_type_check
|
|
203
|
+
@contextmanager
|
|
204
|
+
def hook_unittest(records: HTTPRecords) -> Generator[None, None, None]:
|
|
205
|
+
hooks = False
|
|
206
|
+
try:
|
|
207
|
+
import unittest
|
|
208
|
+
|
|
209
|
+
unittest.case.TestCase.run = decorate(
|
|
210
|
+
records, unittest.case.TestCase.run, set_hook_for_unittest_run
|
|
211
|
+
)
|
|
212
|
+
unittest.case.TestCase._callSetUp = decorate(
|
|
213
|
+
records, unittest.case.TestCase._callSetUp, set_hook_for_unittest_fixture
|
|
214
|
+
)
|
|
215
|
+
unittest.case.TestCase._callTearDown = decorate(
|
|
216
|
+
records, unittest.case.TestCase._callTearDown, set_hook_for_unittest_fixture
|
|
217
|
+
)
|
|
218
|
+
unittest.suite.TestSuite._handleClassSetUp = decorate(
|
|
219
|
+
records,
|
|
220
|
+
unittest.suite.TestSuite._handleClassSetUp,
|
|
221
|
+
set_hook_for_unittest_class_setup,
|
|
222
|
+
)
|
|
223
|
+
unittest.suite.TestSuite._tearDownPreviousClass = decorate(
|
|
224
|
+
records,
|
|
225
|
+
unittest.suite.TestSuite._tearDownPreviousClass,
|
|
226
|
+
set_hook_for_unittest_class_teardown,
|
|
227
|
+
)
|
|
228
|
+
unittest.suite.TestSuite._handleModuleFixture = decorate(
|
|
229
|
+
records,
|
|
230
|
+
unittest.suite.TestSuite._handleModuleFixture,
|
|
231
|
+
set_hook_for_unittest_module_setup,
|
|
232
|
+
)
|
|
233
|
+
unittest.suite.TestSuite._handleModuleTearDown = decorate(
|
|
234
|
+
records,
|
|
235
|
+
unittest.suite.TestSuite._handleModuleTearDown,
|
|
236
|
+
set_hook_for_unittest_module_teardown,
|
|
237
|
+
)
|
|
238
|
+
hooks = True
|
|
239
|
+
except ImportError:
|
|
240
|
+
pass
|
|
241
|
+
|
|
242
|
+
yield
|
|
243
|
+
|
|
244
|
+
if hooks:
|
|
245
|
+
unittest.case.TestCase.run = undecorate(unittest.case.TestCase.run)
|
|
246
|
+
unittest.case.TestCase._callSetUp = undecorate(
|
|
247
|
+
unittest.case.TestCase._callSetUp
|
|
248
|
+
)
|
|
249
|
+
unittest.case.TestCase._callTearDown = undecorate(
|
|
250
|
+
unittest.case.TestCase._callTearDown
|
|
251
|
+
)
|
|
252
|
+
unittest.suite.TestSuite._handleClassSetUp = undecorate(
|
|
253
|
+
unittest.suite.TestSuite._handleClassSetUp
|
|
254
|
+
)
|
|
255
|
+
unittest.suite.TestSuite._tearDownPreviousClass = undecorate(
|
|
256
|
+
unittest.suite.TestSuite._tearDownPreviousClass
|
|
257
|
+
)
|
|
258
|
+
unittest.suite.TestSuite._handleModuleFixture = undecorate(
|
|
259
|
+
unittest.suite.TestSuite._handleModuleFixture
|
|
260
|
+
)
|
|
261
|
+
unittest.suite.TestSuite._handleModuleTearDown = undecorate(
|
|
262
|
+
unittest.suite.TestSuite._handleModuleTearDown
|
|
263
|
+
)
|
|
@@ -4,6 +4,8 @@ import sys
|
|
|
4
4
|
import traceback
|
|
5
5
|
from typing import List
|
|
6
6
|
|
|
7
|
+
from httpdbg.log import logger
|
|
8
|
+
|
|
7
9
|
|
|
8
10
|
def run_script(argv: List[str]) -> None:
|
|
9
11
|
sys.argv = argv
|
|
@@ -15,6 +17,15 @@ def run_script(argv: List[str]) -> None:
|
|
|
15
17
|
except AttributeError:
|
|
16
18
|
exit("script mode - error - the first argument shall be a python file")
|
|
17
19
|
try:
|
|
20
|
+
original__main___module = sys.modules["__main__"]
|
|
21
|
+
sys.modules["__main__"] = module # mandatory to execute a unittest test file.
|
|
18
22
|
spec.loader.exec_module(module) # type: ignore
|
|
19
23
|
except Exception:
|
|
20
24
|
traceback.print_exc()
|
|
25
|
+
except SystemExit as ex:
|
|
26
|
+
# in some case, for example when executing unittest tests from a script,
|
|
27
|
+
# the SystemExit exception is raised by the script itself so we catch it.
|
|
28
|
+
# TODO propagate the SystemExit value when httpdbg terminates.
|
|
29
|
+
logger().info(f"run_script - exception SystemExit - {str(ex)}")
|
|
30
|
+
finally:
|
|
31
|
+
sys.modules["__main__"] = original__main___module
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: httpdbg
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.30.0
|
|
4
4
|
Summary: A very simple tool to debug HTTP(S) client requests
|
|
5
5
|
Author-email: cle-b <cle@tictac.pm>
|
|
6
6
|
License: Apache-2.0
|
|
@@ -116,6 +116,7 @@ You can use any package as an initiator, this is not limited to HTTP requests.
|
|
|
116
116
|
| httpx | supported |
|
|
117
117
|
| aiohttp | supported |
|
|
118
118
|
| pytest | supported |
|
|
119
|
+
| unittest | supported |
|
|
119
120
|
| _your_package_ | yes, with the arg _-i your_package_ |
|
|
120
121
|
|
|
121
122
|
## configuration
|
|
@@ -31,6 +31,7 @@ httpdbg/hooks/httpx.py
|
|
|
31
31
|
httpdbg/hooks/pytest.py
|
|
32
32
|
httpdbg/hooks/requests.py
|
|
33
33
|
httpdbg/hooks/socket.py
|
|
34
|
+
httpdbg/hooks/unittest.py
|
|
34
35
|
httpdbg/hooks/urllib3.py
|
|
35
36
|
httpdbg/hooks/utils.py
|
|
36
37
|
httpdbg/webapp/__init__.py
|
|
@@ -64,7 +65,9 @@ tests/test_cli.py
|
|
|
64
65
|
tests/test_context_manager.py
|
|
65
66
|
tests/test_hook_aiohttp.py
|
|
66
67
|
tests/test_hook_httpx.py
|
|
68
|
+
tests/test_hook_pytest.py
|
|
67
69
|
tests/test_hook_requests.py
|
|
70
|
+
tests/test_hook_unittest.py
|
|
68
71
|
tests/test_hook_urllib3.py
|
|
69
72
|
tests/test_initiator.py
|
|
70
73
|
tests/test_mode_console.py
|
|
@@ -6,8 +6,8 @@ import pytest
|
|
|
6
6
|
from httpdbg.hooks.all import httprecord
|
|
7
7
|
from httpdbg.server import httpdbg_srv
|
|
8
8
|
|
|
9
|
-
from utils import get_request_content_up
|
|
10
|
-
from utils import get_request_details
|
|
9
|
+
from tests.utils import get_request_content_up
|
|
10
|
+
from tests.utils import get_request_details
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
@pytest.mark.api
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
import pytest
|
|
5
|
+
|
|
6
|
+
from httpdbg.mode_module import run_module
|
|
7
|
+
from httpdbg.hooks.all import httprecord
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@pytest.mark.pytest
|
|
11
|
+
@pytest.mark.group
|
|
12
|
+
@pytest.mark.tag
|
|
13
|
+
def test_run_pytest_tag(httpbin):
|
|
14
|
+
with httprecord() as records:
|
|
15
|
+
os.environ["HTTPDBG_TEST_PYTEST_BASE_URL"] = httpbin.url
|
|
16
|
+
script_to_run = os.path.join(
|
|
17
|
+
os.path.dirname(os.path.realpath(__file__)), "demo_run_pytest.py"
|
|
18
|
+
)
|
|
19
|
+
run_module(["pytest", f"{script_to_run}::test_demo_pytest_fixture_tag"])
|
|
20
|
+
|
|
21
|
+
assert len(records) == 2
|
|
22
|
+
groups = records.groups
|
|
23
|
+
|
|
24
|
+
assert records[0].url.endswith("/post")
|
|
25
|
+
assert groups[records[0].group_id].label == "test_demo_pytest_fixture_tag"
|
|
26
|
+
assert (
|
|
27
|
+
"demo_run_pytest.py::test_demo_pytest_fixture_tag"
|
|
28
|
+
in groups[records[0].group_id].full_label
|
|
29
|
+
)
|
|
30
|
+
assert records[0].tag == "my_fixture"
|
|
31
|
+
|
|
32
|
+
assert records[1].url.endswith("/get")
|
|
33
|
+
assert groups[records[1].group_id].label == "test_demo_pytest_fixture_tag"
|
|
34
|
+
assert (
|
|
35
|
+
"demo_run_pytest.py::test_demo_pytest_fixture_tag"
|
|
36
|
+
in groups[records[1].group_id].full_label
|
|
37
|
+
)
|
|
38
|
+
assert records[1].tag is None
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
import pytest
|
|
5
|
+
|
|
6
|
+
from httpdbg.mode_module import run_module
|
|
7
|
+
from httpdbg.mode_script import run_script
|
|
8
|
+
from httpdbg.hooks.all import httprecord
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@pytest.mark.unittest
|
|
12
|
+
@pytest.mark.group
|
|
13
|
+
@pytest.mark.tag
|
|
14
|
+
def test_run_module_unittest(httpbin):
|
|
15
|
+
with httprecord() as records:
|
|
16
|
+
os.environ["HTTPDBG_TEST_UNITTEST_BASE_URL"] = httpbin.url
|
|
17
|
+
script_to_run = os.path.join(
|
|
18
|
+
os.path.dirname(os.path.realpath(__file__)), "demo_run_unittest.py"
|
|
19
|
+
)
|
|
20
|
+
run_module(["unittest", f"{script_to_run}"])
|
|
21
|
+
|
|
22
|
+
assert_unittest_records(records)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@pytest.mark.unittest
|
|
26
|
+
@pytest.mark.group
|
|
27
|
+
@pytest.mark.tag
|
|
28
|
+
def test_run_script_unittest(httpbin):
|
|
29
|
+
with httprecord() as records:
|
|
30
|
+
os.environ["HTTPDBG_TEST_UNITTEST_BASE_URL"] = httpbin.url
|
|
31
|
+
script_to_run = os.path.join(
|
|
32
|
+
os.path.dirname(os.path.realpath(__file__)), "demo_run_unittest.py"
|
|
33
|
+
)
|
|
34
|
+
run_script([f"{script_to_run}"])
|
|
35
|
+
|
|
36
|
+
assert_unittest_records(records)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def assert_unittest_records(records):
|
|
40
|
+
|
|
41
|
+
assert len(records) == 10
|
|
42
|
+
groups = records.groups
|
|
43
|
+
|
|
44
|
+
i_req = 0
|
|
45
|
+
assert records[i_req].url.endswith("/setup_module")
|
|
46
|
+
assert groups[records[i_req].group_id].label == "setUpModule (demo_run_unittest)"
|
|
47
|
+
assert (
|
|
48
|
+
"demo_run_unittest.py::setUpModule"
|
|
49
|
+
in groups[records[i_req].group_id].full_label
|
|
50
|
+
)
|
|
51
|
+
assert records[i_req].tag is None
|
|
52
|
+
|
|
53
|
+
i_req = 1
|
|
54
|
+
assert records[i_req].url.endswith("/setup_class")
|
|
55
|
+
assert groups[records[i_req].group_id].label == "TestUnittests::setUpClass"
|
|
56
|
+
assert (
|
|
57
|
+
"demo_run_unittest.py::TestUnittests::setUpClass"
|
|
58
|
+
in groups[records[i_req].group_id].full_label
|
|
59
|
+
)
|
|
60
|
+
assert records[i_req].tag is None
|
|
61
|
+
|
|
62
|
+
i_req = 2
|
|
63
|
+
assert records[i_req].url.endswith("/setup")
|
|
64
|
+
assert groups[records[i_req].group_id].label == "TestUnittests::test_case1"
|
|
65
|
+
assert (
|
|
66
|
+
"demo_run_unittest.py::TestUnittests::test_case1"
|
|
67
|
+
in groups[records[i_req].group_id].full_label
|
|
68
|
+
)
|
|
69
|
+
assert records[i_req].tag == "setUp"
|
|
70
|
+
|
|
71
|
+
i_req = 3
|
|
72
|
+
assert records[i_req].url.endswith("/testcase1")
|
|
73
|
+
assert groups[records[i_req].group_id].label == "TestUnittests::test_case1"
|
|
74
|
+
assert (
|
|
75
|
+
"demo_run_unittest.py::TestUnittests::test_case1"
|
|
76
|
+
in groups[records[i_req].group_id].full_label
|
|
77
|
+
)
|
|
78
|
+
assert records[i_req].tag is None
|
|
79
|
+
|
|
80
|
+
i_req = 4
|
|
81
|
+
assert records[i_req].url.endswith("/teardown")
|
|
82
|
+
assert groups[records[i_req].group_id].label == "TestUnittests::test_case1"
|
|
83
|
+
assert (
|
|
84
|
+
"demo_run_unittest.py::TestUnittests::test_case1"
|
|
85
|
+
in groups[records[i_req].group_id].full_label
|
|
86
|
+
)
|
|
87
|
+
assert records[i_req].tag == "tearDown"
|
|
88
|
+
|
|
89
|
+
i_req = 5
|
|
90
|
+
assert records[i_req].url.endswith("/setup")
|
|
91
|
+
assert groups[records[i_req].group_id].label == "TestUnittests::test_case2"
|
|
92
|
+
assert (
|
|
93
|
+
"demo_run_unittest.py::TestUnittests::test_case2"
|
|
94
|
+
in groups[records[i_req].group_id].full_label
|
|
95
|
+
)
|
|
96
|
+
assert records[i_req].tag == "setUp"
|
|
97
|
+
|
|
98
|
+
i_req = 6
|
|
99
|
+
assert records[i_req].url.endswith("/testcase2")
|
|
100
|
+
assert groups[records[i_req].group_id].label == "TestUnittests::test_case2"
|
|
101
|
+
assert (
|
|
102
|
+
"demo_run_unittest.py::TestUnittests::test_case2"
|
|
103
|
+
in groups[records[i_req].group_id].full_label
|
|
104
|
+
)
|
|
105
|
+
assert records[i_req].tag is None
|
|
106
|
+
|
|
107
|
+
i_req = 7
|
|
108
|
+
assert records[i_req].url.endswith("/teardown")
|
|
109
|
+
assert groups[records[i_req].group_id].label == "TestUnittests::test_case2"
|
|
110
|
+
assert (
|
|
111
|
+
"demo_run_unittest.py::TestUnittests::test_case2"
|
|
112
|
+
in groups[records[i_req].group_id].full_label
|
|
113
|
+
)
|
|
114
|
+
assert records[i_req].tag == "tearDown"
|
|
115
|
+
|
|
116
|
+
i_req = 8
|
|
117
|
+
assert records[i_req].url.endswith("/teardown_class")
|
|
118
|
+
assert groups[records[i_req].group_id].label == "TestUnittests::tearDownClass"
|
|
119
|
+
assert (
|
|
120
|
+
"demo_run_unittest.py::TestUnittests::tearDownClass"
|
|
121
|
+
in groups[records[i_req].group_id].full_label
|
|
122
|
+
)
|
|
123
|
+
assert records[i_req].tag is None
|
|
124
|
+
|
|
125
|
+
i_req = 9
|
|
126
|
+
assert records[i_req].url.endswith("/teardown_module")
|
|
127
|
+
assert groups[records[i_req].group_id].label == "tearDownModule (demo_run_unittest)"
|
|
128
|
+
assert (
|
|
129
|
+
"demo_run_unittest.py::tearDownModule"
|
|
130
|
+
in groups[records[i_req].group_id].full_label
|
|
131
|
+
)
|
|
132
|
+
assert records[i_req].tag is None
|
|
@@ -102,12 +102,12 @@ def test_initiator_pytest(httpbin):
|
|
|
102
102
|
)
|
|
103
103
|
def test_initiator_add_package_fnc(httpbin):
|
|
104
104
|
# all cases must be tested in the same test
|
|
105
|
-
with httprecord(initiators=["initiator_pck"]) as records:
|
|
106
|
-
from initiator_pck.initiator2.mod2 import fnc_in_subpackage
|
|
107
|
-
from initiator_pck.mod1 import fnc_in_package
|
|
108
|
-
from initiator_pck import fnc_async
|
|
109
|
-
from initiator_pck.initiator2.initiator3 import fnc_in_init
|
|
110
|
-
from initiator_pck.initiator2.mod2 import FakeClient
|
|
105
|
+
with httprecord(initiators=["tests.initiator_pck"]) as records:
|
|
106
|
+
from tests.initiator_pck.initiator2.mod2 import fnc_in_subpackage
|
|
107
|
+
from tests.initiator_pck.mod1 import fnc_in_package
|
|
108
|
+
from tests.initiator_pck import fnc_async
|
|
109
|
+
from tests.initiator_pck.initiator2.initiator3 import fnc_in_init
|
|
110
|
+
from tests.initiator_pck.initiator2.mod2 import FakeClient
|
|
111
111
|
|
|
112
112
|
fnc_in_package(f"{httpbin.url}/get")
|
|
113
113
|
fnc_in_subpackage(f"{httpbin.url}/get")
|
|
@@ -112,28 +112,3 @@ def test_run_pytest_group(httpbin, httpdbg_host, httpdbg_port):
|
|
|
112
112
|
|
|
113
113
|
assert group["label"] == "test_demo_pytest"
|
|
114
114
|
assert group["full_label"] == "tests/demo_run_pytest.py::test_demo_pytest"
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
@pytest.mark.api
|
|
118
|
-
@pytest.mark.pytest
|
|
119
|
-
@pytest.mark.tag
|
|
120
|
-
def test_run_pytest_tag(httpbin, httpdbg_host, httpdbg_port):
|
|
121
|
-
with httpdbg_srv(httpdbg_host, httpdbg_port) as records:
|
|
122
|
-
with httprecord(records):
|
|
123
|
-
os.environ["HTTPDBG_TEST_PYTEST_BASE_URL"] = httpbin.url
|
|
124
|
-
script_to_run = os.path.join(
|
|
125
|
-
os.path.dirname(os.path.realpath(__file__)), "demo_run_pytest.py"
|
|
126
|
-
)
|
|
127
|
-
run_module(["pytest", f"{script_to_run}::test_demo_pytest_fixture_tag"])
|
|
128
|
-
|
|
129
|
-
ret = requests.get(f"http://{httpdbg_host}:{httpdbg_port}/requests")
|
|
130
|
-
|
|
131
|
-
reqs = ret.json()["requests"]
|
|
132
|
-
|
|
133
|
-
assert len(reqs) == 2
|
|
134
|
-
|
|
135
|
-
assert reqs[list(reqs.keys())[0]]["url"] == httpbin.url + "/post"
|
|
136
|
-
assert reqs[list(reqs.keys())[0]]["tag"] == "my_fixture"
|
|
137
|
-
|
|
138
|
-
assert reqs[list(reqs.keys())[1]]["url"] == httpbin.url + "/get"
|
|
139
|
-
assert reqs[list(reqs.keys())[1]]["tag"] is None
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/webapp/static/icons/chevron-direction-top-outline-icon.svg
RENAMED
|
File without changes
|
{httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/webapp/static/icons/download-install-line-icon.svg
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{httpdbg-0.29.2 → httpdbg-0.30.0}/httpdbg/webapp/static/icons/question-mark-round-line-icon.svg
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|