220809
This commit is contained in:
parent
a0190c992d
commit
2e47bbed17
|
@ -438,13 +438,13 @@ function html_escape(s) {
|
||||||
<div id="testinfo" style="max-width: 360px; width: auto; float: left;">
|
<div id="testinfo" style="max-width: 360px; width: auto; float: left;">
|
||||||
<h1 style="margin: 5px 0px 10px 0px; font-family: Microsoft YaHei;">测试报告</h1>
|
<h1 style="margin: 5px 0px 10px 0px; font-family: Microsoft YaHei;">测试报告</h1>
|
||||||
|
|
||||||
<p class='attribute'><strong>开始时间 : </strong> 2022-08-06 18:07:00</p>
|
<p class='attribute'><strong>开始时间 : </strong> 2022-08-09 18:30:10</p>
|
||||||
|
|
||||||
<p class='attribute'><strong>合计耗时 : </strong> 00:00:00</p>
|
<p class='attribute'><strong>合计耗时 : </strong> 00:00:01</p>
|
||||||
|
|
||||||
<p class='attribute'><strong>测试结果 : </strong> 总共 6,通过 5,失败 1,错误 0,通过率 83.33%</p>
|
<p class='attribute'><strong>测试结果 : </strong> 总共 6,通过 5,失败 1,错误 0,通过率 83.33%</p>
|
||||||
|
|
||||||
<p class='attribute'><strong>失败用例 : </strong> <a class='showDetail' data-toggle='collapse' href='#failedCaseOl' style='text-decoration: none;'>点击查看</a><ol id='failedCaseOl' class='collapse' style='float: left; font-family: Menlo,Monaco,Consolas,monospace;'><li>main.测试用例.test0005_None</li></ol></p>
|
<p class='attribute'><strong>失败用例 : </strong> <a class='showDetail' data-toggle='collapse' href='#failedCaseOl' style='text-decoration: none;'>点击查看</a><ol id='failedCaseOl' class='collapse' style='float: left; font-family: Menlo,Monaco,Consolas,monospace;'><li>main.测试用例.test0006_None</li></ol></p>
|
||||||
|
|
||||||
<p class='attribute'><strong>错误用例 : </strong> 无</p>
|
<p class='attribute'><strong>错误用例 : </strong> 无</p>
|
||||||
|
|
||||||
|
@ -493,7 +493,7 @@ function html_escape(s) {
|
||||||
<td class="text-center">5</td>
|
<td class="text-center">5</td>
|
||||||
<td class="text-center">1</td>
|
<td class="text-center">1</td>
|
||||||
<td class="text-center">0</td>
|
<td class="text-center">0</td>
|
||||||
<td class="text-center">0.863秒</td>
|
<td class="text-center">1.123秒</td>
|
||||||
<td class="text-center"><a href="javascript:showClassDetail('c1',6)" class="detail" id='c1'>查看全部</a></td>
|
<td class="text-center"><a href="javascript:showClassDetail('c1',6)" class="detail" id='c1'>查看全部</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
@ -525,42 +525,42 @@ function html_escape(s) {
|
||||||
<td class='passedCase' style="vertical-align: middle"></td>
|
<td class='passedCase' style="vertical-align: middle"></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr id='ft1_5' class='none'>
|
<tr id='pt1_5' class='hiddenRow'>
|
||||||
<td class='failedCase' style="vertical-align: middle"><div class='testcase'>test0005_None</div></td>
|
<td class='passedCase' style="vertical-align: middle"><div class='testcase'>test0005_None</div></td>
|
||||||
|
<td style="vertical-align: left"></td>
|
||||||
|
<td colspan='5' align='center'><button type="button" class="btn btn-xs">通过</button></td>
|
||||||
|
<td class='passedCase' style="vertical-align: middle"></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr id='ft1_6' class='none'>
|
||||||
|
<td class='failedCase' style="vertical-align: middle"><div class='testcase'>test0006_None</div></td>
|
||||||
<td style="vertical-align: middle"></td>
|
<td style="vertical-align: middle"></td>
|
||||||
<td colspan='5' align='center'>
|
<td colspan='5' align='center'>
|
||||||
<button id='btn_ft1_5' type="button" class="btn btn-xs" data-toggle="collapse" data-target='#div_ft1_5'>失败</button>
|
<button id='btn_ft1_6' type="button" class="btn btn-xs" data-toggle="collapse" data-target='#div_ft1_6'>失败</button>
|
||||||
<div id='div_ft1_5' class="collapse in">
|
<div id='div_ft1_6' class="collapse in">
|
||||||
<pre style="text-align:left;font-size:12px;color:#e52000">ft1_5:
|
<pre style="text-align:left;font-size:12px;color:#e52000">ft1_6:
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
File "D:\Project\AutoFramework\Runner\API\DefaultRunner.py", line 413, in foo
|
File "D:\Project\AutoFramework\Runner\API\DefaultRunner.py", line 499, in foo
|
||||||
return self._test_(index)
|
return self._test_(index)
|
||||||
File "D:\Project\AutoFramework\Runner\API\DefaultRunner.py", line 398, in test
|
File "D:\Project\AutoFramework\Runner\API\DefaultRunner.py", line 484, in test
|
||||||
self.test_unit(data=main_case)
|
self.test_unit(data=main_case)
|
||||||
File "D:\Project\AutoFramework\Runner\API\DefaultRunner.py", line 383, in test_unit
|
File "D:\Project\AutoFramework\Runner\API\DefaultRunner.py", line 452, in test_unit
|
||||||
exec('assert ' + self._sub_variable_auto(contr).replace('$', str(res['status'])))
|
exec('%s(%s, %s)' % (operator['method'], formula_args[0], formula_args[1]))
|
||||||
File "<string>", line 1, in <module>
|
File "<string>", line 1, in <module>
|
||||||
AssertionError
|
AssertionError: 'nginx2' not found in {'Server': 'nginx', 'Date': 'Tue, 09 Aug 2022 10:30:12 GMT', 'Content-Type': 'application/json', 'Content-Length': '208', 'Last-Modified': 'Thu, 04 Aug 2022 07:51:36 GMT', 'Connection': 'keep-alive', 'ETag': '"62eb7a88-d0"', 'Accept-Ranges': 'bytes', '_': 'Server: nginx\nDate: Tue, 09 Aug 2022 10:30:12 GMT\nContent-Type: application/json\nContent-Length: \'208\'\nLast-Modified: Thu, 04 Aug 2022 07:51:36 GMT\nConnection: keep-alive\nETag: \'"62eb7a88-d0"\'\nAccept-Ranges: bytes\n'}
|
||||||
</pre>
|
</pre>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td class='failedCase' style="vertical-align: middle"></td>
|
<td class='failedCase' style="vertical-align: middle"></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr id='pt1_6' class='hiddenRow'>
|
|
||||||
<td class='passedCase' style="vertical-align: middle"><div class='testcase'>test0006_None</div></td>
|
|
||||||
<td style="vertical-align: left"></td>
|
|
||||||
<td colspan='5' align='center'><button type="button" class="btn btn-xs">通过</button></td>
|
|
||||||
<td class='passedCase' style="vertical-align: middle"></td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr id='total_row' class="text-center active">
|
<tr id='total_row' class="text-center active">
|
||||||
<td colspan='2'>总计</td>
|
<td colspan='2'>总计</td>
|
||||||
<td>6</td>
|
<td>6</td>
|
||||||
<td>5</td>
|
<td>5</td>
|
||||||
<td>1</td>
|
<td>1</td>
|
||||||
<td>0</td>
|
<td>0</td>
|
||||||
<td>0.863秒</td>
|
<td>1.123秒</td>
|
||||||
<td>通过:83.33%</td>
|
<td>通过:83.33%</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
|
@ -13,7 +13,7 @@ def reparse(regexp, string):
|
||||||
import re
|
import re
|
||||||
mut = isinstance(regexp, tuple)
|
mut = isinstance(regexp, tuple)
|
||||||
reg = [str(regexp), str(regexp[0])][mut]
|
reg = [str(regexp), str(regexp[0])][mut]
|
||||||
flg = [0, eval('re.%s' % str(regexp[1]).upper())][mut]
|
flg = (mut and eval('re.%s' % str(regexp[1]).upper())) or 0
|
||||||
if reg in ['', 'trim']:
|
if reg in ['', 'trim']:
|
||||||
return ReText(string.strip())
|
return ReText(string.strip())
|
||||||
else:
|
else:
|
||||||
|
@ -90,6 +90,7 @@ class ReDict(dict):
|
||||||
class TestCase:
|
class TestCase:
|
||||||
_g = {}
|
_g = {}
|
||||||
_l = {}
|
_l = {}
|
||||||
|
unit = unittest.TestCase()
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
|
@ -273,6 +274,48 @@ class TestCase:
|
||||||
dict_ori[k] = dict_add[k]
|
dict_ori[k] = dict_add[k]
|
||||||
return dict_ori
|
return dict_ori
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _parse_formula(text, operator):
|
||||||
|
locals().__setitem__('quota', 0)
|
||||||
|
none_quota = []
|
||||||
|
none_range = []
|
||||||
|
for i in range(len(text)):
|
||||||
|
this = text[i]
|
||||||
|
match this:
|
||||||
|
case '\'':
|
||||||
|
match locals().get('quota'):
|
||||||
|
case 0:
|
||||||
|
locals().__setitem__('quota', 1)
|
||||||
|
case 1:
|
||||||
|
locals().__setitem__('quota', 0)
|
||||||
|
case '\"':
|
||||||
|
match locals().get('quota'):
|
||||||
|
case 0:
|
||||||
|
locals().__setitem__('quota', 2)
|
||||||
|
case 2:
|
||||||
|
locals().__setitem__('quota', 0)
|
||||||
|
case _:
|
||||||
|
match locals().get('quota'):
|
||||||
|
case 0:
|
||||||
|
none_quota.append(i)
|
||||||
|
for i in range(len(none_quota) + 1):
|
||||||
|
last = (i > 0 and none_quota[i - 1]) or -1
|
||||||
|
this = (i < len(none_quota) and none_quota[i]) or 9999
|
||||||
|
if (this - last) > 1:
|
||||||
|
none_range.append(last)
|
||||||
|
none_range.append(this)
|
||||||
|
none_range.pop(0)
|
||||||
|
none_range.pop(-1)
|
||||||
|
none_range_list = []
|
||||||
|
for i in range(int(len(none_range) / 2)):
|
||||||
|
none_range_list.append([none_range[i * 2], none_range[i * 2 + 1]])
|
||||||
|
for v in none_range_list:
|
||||||
|
p = text.find(operator, v[0], v[1] + 1)
|
||||||
|
if not p == -1:
|
||||||
|
return [text[:p], text[p + len(operator):]]
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _sub_variable(text='', vars_dict=None):
|
def _sub_variable(text='', vars_dict=None):
|
||||||
if not isinstance(text, str):
|
if not isinstance(text, str):
|
||||||
|
@ -365,30 +408,75 @@ class TestCase:
|
||||||
json_encode(bool(0)): bool(0),
|
json_encode(bool(0)): bool(0),
|
||||||
json_encode(bool(1)): bool(1)
|
json_encode(bool(1)): bool(1)
|
||||||
}.items():
|
}.items():
|
||||||
locals().setdefault(var_name, var_value)
|
locals().__setitem__(var_name, var_value)
|
||||||
for k, v in (auto_decode(data['HTTPExtract']) or {}).items():
|
for k, v in (auto_decode(data['HTTPExtract']) or {}).items():
|
||||||
d = re.findall('^([0-9A-Za-z_]+).*?', v)[0]
|
d = re.findall('^([0-9A-Za-z_]+).*?', v)[0]
|
||||||
self._g[str(k)] = str(eval('_' + v.replace(d, d.title(), 1)))
|
self._g[str(k)] = str(eval('_' + v.replace(d, d.title(), 1)))
|
||||||
|
for assert_item in [
|
||||||
|
{'expect': data['HTTPAssertStatus'], 'actual': locals().get('_Status')},
|
||||||
|
{'expect': data['HTTPAssertReason'], 'actual': locals().get('_Reason')},
|
||||||
|
{'expect': data['HTTPAssertHeader'], 'actual': locals().get('_Header')},
|
||||||
|
{'expect': data['HTTPAssertCookie'], 'actual': locals().get('_Cookie')},
|
||||||
|
{'expect': data['HTTPAssertBody'], 'actual': locals().get('_Body')},
|
||||||
|
{'expect': data['HTTPAssertJson'], 'actual': locals().get('_Json')},
|
||||||
|
]:
|
||||||
|
actual = assert_item['actual']
|
||||||
|
if isinstance(actual, (int, bool, str)):
|
||||||
|
actual = ReText(actual)
|
||||||
|
if isinstance(actual, (tuple, list, set)):
|
||||||
|
actual = ReList(actual)
|
||||||
|
if isinstance(actual, (dict, )):
|
||||||
|
actual = ReDict(actual)
|
||||||
|
expect = self._to_string(assert_item['expect'])
|
||||||
|
if expect:
|
||||||
|
expect_nums = 0
|
||||||
|
expect_flag = 0
|
||||||
|
for line in list(filter(lambda x: x, expect.split("\n"))):
|
||||||
|
expect_nums += 1
|
||||||
|
for operator in [
|
||||||
|
{'sign': ' == ', 'method': 'self.unit.assertEqual', 'reverse': 0},
|
||||||
|
{'sign': ' != ', 'method': 'self.unit.assertNotEqual', 'reverse': 0},
|
||||||
|
{'sign': ' >= ', 'method': 'self.unit.assertGreaterEqual', 'reverse': 0},
|
||||||
|
{'sign': ' <= ', 'method': 'self.unit.assertLessEqual', 'reverse': 0},
|
||||||
|
{'sign': ' =~ ', 'method': 'self.unit.assertIn', 'reverse': 1},
|
||||||
|
{'sign': ' !~ ', 'method': 'self.unit.assertNotIn', 'reverse': 1},
|
||||||
|
{'sign': ' > ', 'method': 'self.unit.assertGreater', 'reverse': 0},
|
||||||
|
{'sign': ' < ', 'method': 'self.unit.assertLess', 'reverse': 0},
|
||||||
|
{'sign': ' not in ', 'method': 'self.unit.assertNotIn', 'reverse': 0},
|
||||||
|
{'sign': ' in ', 'method': 'self.unit.assertIn', 'reverse': 0},
|
||||||
|
]:
|
||||||
|
formula_args = self._parse_formula(self._sub_variable_auto(line).replace('$', 'actual'), operator['sign'])
|
||||||
|
if formula_args:
|
||||||
|
expect_flag += 1
|
||||||
|
operator['reverse'] and formula_args.reverse()
|
||||||
|
exec('%s(%s, %s)' % (operator['method'], formula_args[0], formula_args[1]))
|
||||||
|
break
|
||||||
|
if 1 <= expect_flag != expect_nums:
|
||||||
|
raise Exception('wrong assertion statement')
|
||||||
|
if 0 == expect_flag:
|
||||||
|
self.unit.assertEqual(str(actual), expect)
|
||||||
|
|
||||||
expect = self._to_string(data['HTTPAssertStatus'])
|
|
||||||
if expect:
|
|
||||||
opers = [" == ", " != ", " >= ", " <= ", " > ", " < ", " in ", " not in "]
|
# expect = self._to_string(data['HTTPAssertStatus'])
|
||||||
opers_flag = 0
|
# if expect:
|
||||||
for v in opers:
|
# opers = [" == ", " != ", " >= ", " <= ", " > ", " < ", " in ", " not in "]
|
||||||
if v in expect:
|
# opers_flag = 0
|
||||||
opers_flag = 1
|
# for v in opers:
|
||||||
break
|
# if v in expect:
|
||||||
if opers_flag:
|
# opers_flag = 1
|
||||||
contrast = list(filter(lambda x: x, expect.split("\n")))
|
# break
|
||||||
for contr in contrast:
|
# if opers_flag:
|
||||||
exec('assert ' + self._sub_variable_auto(contr).replace('$', str(res['status'])))
|
# contrast = list(filter(lambda x: x, expect.split("\n")))
|
||||||
else:
|
# for contr in contrast:
|
||||||
actual = str(res['status'])
|
# exec('assert ' + self._sub_variable_auto(contr).replace('$', str(res['status'])))
|
||||||
try:
|
# else:
|
||||||
assert expect == actual
|
# actual = str(res['status'])
|
||||||
except AssertionError as e:
|
# try:
|
||||||
raise AssertionError(str(expect) + ' == ' + str(actual))
|
# assert expect == actual
|
||||||
# sys.stderr.write()
|
# except AssertionError as e:
|
||||||
|
# raise AssertionError(str(expect) + ' == ' + str(actual))
|
||||||
|
# # sys.stderr.write()
|
||||||
|
|
||||||
def test(self, index):
|
def test(self, index):
|
||||||
# print(view_case.loc[index])
|
# print(view_case.loc[index])
|
||||||
|
|
52
main3.py
52
main3.py
|
@ -69,14 +69,10 @@ string = '"it in the ..." in "..."'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def func(text=' $["data"][0]["name"] in "it in the ..."'):
|
def _parse_formula(text, operator):
|
||||||
operator_list = [
|
|
||||||
' in ',
|
|
||||||
' == '
|
|
||||||
]
|
|
||||||
locals().__setitem__('quota', 0)
|
locals().__setitem__('quota', 0)
|
||||||
none_quota = []
|
none_quota = []
|
||||||
none_quota_range = []
|
none_range = []
|
||||||
for i in range(len(text)):
|
for i in range(len(text)):
|
||||||
this = text[i]
|
this = text[i]
|
||||||
match this:
|
match this:
|
||||||
|
@ -93,27 +89,25 @@ def func(text=' $["data"][0]["name"] in "it in the ..."'):
|
||||||
case 2:
|
case 2:
|
||||||
locals().__setitem__('quota', 0)
|
locals().__setitem__('quota', 0)
|
||||||
case _:
|
case _:
|
||||||
if locals().get('quota') == 0:
|
match locals().get('quota'):
|
||||||
if none_quota_range:
|
case 0:
|
||||||
if (i-1) != none_quota[-1]:
|
none_quota.append(i)
|
||||||
if (i-none_quota[-1]) > 0:
|
for i in range(len(none_quota) + 1):
|
||||||
none_quota_range.append(none_quota[-1])
|
last = (i > 0 and none_quota[i-1]) or -1
|
||||||
none_quota_range.append(i)
|
this = (i < len(none_quota) and none_quota[i]) or 9999
|
||||||
# if (i-1) == none_quota_range[-1]:
|
if (this - last) > 1:
|
||||||
# pass
|
none_range.append(last)
|
||||||
# none_quota_range.append(none_quota[-1])
|
none_range.append(this)
|
||||||
else:
|
none_range.pop(0)
|
||||||
none_quota_range.append(i)
|
none_range.pop(-1)
|
||||||
none_quota.append(i)
|
none_range_list = []
|
||||||
|
for i in range(int(len(none_range)/2)):
|
||||||
|
none_range_list.append([none_range[i*2], none_range[i*2+1]])
|
||||||
|
for v in none_range_list:
|
||||||
|
p = text.find(operator, v[0], v[1]+1)
|
||||||
|
if not p == -1:
|
||||||
|
return [text[:p], text[p+len(operator):]]
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
print(func('$data["info"][0] == true'))
|
||||||
print(locals().__getitem__('quota'))
|
|
||||||
print(none_quota_range)
|
|
||||||
print(none_quota)
|
|
||||||
|
|
||||||
|
|
||||||
print(func())
|
|
||||||
#
|
|
||||||
# a = 123
|
|
||||||
# locals().__setitem__('a', 456)
|
|
||||||
# print(locals().__getitem__('a'))
|
|
||||||
|
|
Loading…
Reference in New Issue