This commit is contained in:
zhaoyafan 2022-08-09 18:33:27 +08:00
parent a0190c992d
commit 2e47bbed17
4 changed files with 163 additions and 74 deletions

View File

@ -438,13 +438,13 @@ function html_escape(s) {
<div id="testinfo" style="max-width: 360px; width: auto; float: left;">
<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> <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>
@ -493,7 +493,7 @@ function html_escape(s) {
<td class="text-center">5</td>
<td class="text-center">1</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>
</tr>
@ -525,42 +525,42 @@ function html_escape(s) {
<td class='passedCase' style="vertical-align: middle"></td>
</tr>
<tr id='ft1_5' class='none'>
<td class='failedCase' style="vertical-align: middle"><div class='testcase'>test0005_None</div></td>
<tr id='pt1_5' class='hiddenRow'>
<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 colspan='5' align='center'>
<button id='btn_ft1_5' type="button" class="btn btn-xs" data-toggle="collapse" data-target='#div_ft1_5'>失败</button>
<div id='div_ft1_5' class="collapse in">
<pre style="text-align:left;font-size:12px;color:#e52000">ft1_5:
<button id='btn_ft1_6' type="button" class="btn btn-xs" data-toggle="collapse" data-target='#div_ft1_6'>失败</button>
<div id='div_ft1_6' class="collapse in">
<pre style="text-align:left;font-size:12px;color:#e52000">ft1_6:
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)
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)
File "D:\Project\AutoFramework\Runner\API\DefaultRunner.py", line 383, in test_unit
exec('assert ' + self._sub_variable_auto(contr).replace('$', str(res['status'])))
File "D:\Project\AutoFramework\Runner\API\DefaultRunner.py", line 452, in test_unit
exec('%s(%s, %s)' % (operator['method'], formula_args[0], formula_args[1]))
File "&lt;string&gt;", line 1, in &lt;module&gt;
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>
</div>
</td>
<td class='failedCase' style="vertical-align: middle"></td>
</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">
<td colspan='2'>总计</td>
<td>6</td>
<td>5</td>
<td>1</td>
<td>0</td>
<td>0.863秒</td>
<td>1.123秒</td>
<td>通过83.33%</td>
</tr>
</table>

View File

@ -13,7 +13,7 @@ def reparse(regexp, string):
import re
mut = isinstance(regexp, tuple)
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']:
return ReText(string.strip())
else:
@ -90,6 +90,7 @@ class ReDict(dict):
class TestCase:
_g = {}
_l = {}
unit = unittest.TestCase()
def __init__(
self,
@ -273,6 +274,48 @@ class TestCase:
dict_ori[k] = dict_add[k]
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
def _sub_variable(text='', vars_dict=None):
if not isinstance(text, str):
@ -365,30 +408,75 @@ class TestCase:
json_encode(bool(0)): bool(0),
json_encode(bool(1)): bool(1)
}.items():
locals().setdefault(var_name, var_value)
locals().__setitem__(var_name, var_value)
for k, v in (auto_decode(data['HTTPExtract']) or {}).items():
d = re.findall('^([0-9A-Za-z_]+).*?', v)[0]
self._g[str(k)] = str(eval('_' + v.replace(d, d.title(), 1)))
expect = self._to_string(data['HTTPAssertStatus'])
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:
opers = [" == ", " != ", " >= ", " <= ", " > ", " < ", " in ", " not in "]
opers_flag = 0
for v in opers:
if v in expect:
opers_flag = 1
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 opers_flag:
contrast = list(filter(lambda x: x, expect.split("\n")))
for contr in contrast:
exec('assert ' + self._sub_variable_auto(contr).replace('$', str(res['status'])))
else:
actual = str(res['status'])
try:
assert expect == actual
except AssertionError as e:
raise AssertionError(str(expect) + ' == ' + str(actual))
# sys.stderr.write()
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 "]
# opers_flag = 0
# for v in opers:
# if v in expect:
# opers_flag = 1
# break
# if opers_flag:
# contrast = list(filter(lambda x: x, expect.split("\n")))
# for contr in contrast:
# exec('assert ' + self._sub_variable_auto(contr).replace('$', str(res['status'])))
# else:
# actual = str(res['status'])
# try:
# assert expect == actual
# except AssertionError as e:
# raise AssertionError(str(expect) + ' == ' + str(actual))
# # sys.stderr.write()
def test(self, index):
# print(view_case.loc[index])

View File

@ -69,14 +69,10 @@ string = '"it in the ..." in "..."'
def func(text=' $["data"][0]["name"] in "it in the ..."'):
operator_list = [
' in ',
' == '
]
def _parse_formula(text, operator):
locals().__setitem__('quota', 0)
none_quota = []
none_quota_range = []
none_range = []
for i in range(len(text)):
this = text[i]
match this:
@ -93,27 +89,25 @@ def func(text=' $["data"][0]["name"] in "it in the ..."'):
case 2:
locals().__setitem__('quota', 0)
case _:
if locals().get('quota') == 0:
if none_quota_range:
if (i-1) != none_quota[-1]:
if (i-none_quota[-1]) > 0:
none_quota_range.append(none_quota[-1])
none_quota_range.append(i)
# if (i-1) == none_quota_range[-1]:
# pass
# none_quota_range.append(none_quota[-1])
else:
none_quota_range.append(i)
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
print(locals().__getitem__('quota'))
print(none_quota_range)
print(none_quota)
print(func())
#
# a = 123
# locals().__setitem__('a', 456)
# print(locals().__getitem__('a'))
print(func('$data["info"][0] == true'))

View File

@ -1,2 +1,9 @@
if [0]:
print(1)
import unittest
# ut = unittest.TestCase()
# ut.assertEqual('1', '1')
# # ut.assertIn('1234', '123')
# ut.assertLessEqual('4','3')
# ut.assert
l = [1, 2]
print(l.reverse())
print(l)